diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 43a751c..b447688 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -6,7 +6,7 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended' ], - ignorePatterns: ['dist', '.eslintrc.cjs', 'licenseChecker.cjs'], + ignorePatterns: ['dist', '.eslintrc.cjs', 'licenseChecker.cjs', "*.min.js"], parser: '@typescript-eslint/parser', plugins: ['react-refresh'], rules: { diff --git a/contributing.md b/contributing.md index bac274e..ddff155 100644 --- a/contributing.md +++ b/contributing.md @@ -6,19 +6,19 @@ Welcome to Sigit! We are thrilled that you are interested in contributing to thi ### Reporting Bugs -If you encounter a bug while using Sigit, please [open an issue](https://git.sigit.io/g/web/issues/new) on this repository. Provide as much detail as possible, including steps to reproduce the bug. +If you encounter a bug while using Sigit, please [open an issue](https://git.nostrdev.com/sigit/sigit.io/issues/new) on this repository. Provide as much detail as possible, including steps to reproduce the bug. ### Suggesting Enhancements -If you have an idea for how to improve Sigit, we would love to hear from you! [Open an issue](https://git.sigit.io/g/web/issues/new) to suggest an enhancement. +If you have an idea for how to improve Sigit, we would love to hear from you! [Open an issue](https://git.nostrdev.com/sigit/sigit.io/issues/new) to suggest an enhancement. ### Pull Requests We welcome pull requests from contributors! To contribute code changes: -1. Fork the repository and create your branch from `main`. +1. Fork the repository and create your branch from `staging`. 2. Make your changes and ensure they pass any existing tests. -3. Write meaningful commit messages. +3. Write meaningful commit messages (conventional commit standard) 4. Submit a pull request, describing your changes in detail and referencing any related issues. ## Development Setup @@ -35,4 +35,14 @@ All contributions, including pull requests, undergo code review. Code review ens ## Contact -If you have questions or need further assistance, you can reach out to [maintainer's email]. +If you have questions or need further assistance, you can reach out to `npub1d0csynrrxcynkcedktdzrdj6gnras2psg48mf46kxjazs8skrjgq9uzhlq` + +## Testing + +The following items should be tested with each release: + +- Create a SIGit with at least 3 signers +- Create a SIGit where the creator is not the first signer +- Create a SIGit where one co-signer has no marks +- Create a SIGit using a file other than a PDF +- Use several login mechanisms, browsers, operating systems whilst testing diff --git a/index.html b/index.html index 234938f..501fda6 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,7 @@
+ diff --git a/package-lock.json b/package-lock.json index a9fb01a..65fb09a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sigit", - "version": "0.0.0", + "version": "0.0.0-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sigit", - "version": "0.0.0", + "version": "0.0.0-beta", "hasInstallScript": true, "license": "AGPL-3.0-or-later ", "dependencies": { @@ -20,19 +20,22 @@ "@mui/lab": "5.0.0-alpha.166", "@mui/material": "5.15.11", "@noble/hashes": "^1.4.0", - "@nostr-dev-kit/ndk": "2.5.0", + "@nostr-dev-kit/ndk": "2.10.0", + "@nostr-dev-kit/ndk-cache-dexie": "2.5.1", "@pdf-lib/fontkit": "^1.1.1", "@reduxjs/toolkit": "2.2.1", "axios": "^1.7.4", "crypto-hash": "3.0.0", "crypto-js": "^4.2.0", + "dexie": "4.0.8", "dnd-core": "16.0.1", "file-saver": "2.0.5", "idb": "8.0.0", "jszip": "3.10.1", "lodash": "4.17.21", + "material-ui-popup-state": "^5.3.1", "mui-file-input": "4.0.4", - "nostr-login": "^1.6.6", + "nostr-login": "1.6.14", "nostr-tools": "2.7.0", "pdf-lib": "^1.17.1", "pdfjs-dist": "^4.4.168", @@ -47,7 +50,9 @@ "react-singleton-hook": "^4.0.1", "react-toastify": "10.0.4", "redux": "5.0.1", - "tseep": "1.2.1" + "signature_pad": "^5.0.4", + "tseep": "1.2.1", + "use-immer": "^0.11.0" }, "devDependencies": { "@types/crypto-js": "^4.2.2", @@ -56,6 +61,7 @@ "@types/pdfjs-dist": "^2.10.378", "@types/react": "^18.2.56", "@types/react-dom": "^18.2.19", + "@types/svgo": "^3.0.0", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", "@vitejs/plugin-react": "^4.2.1", @@ -68,6 +74,7 @@ "ts-css-modules-vite-plugin": "1.0.20", "typescript": "^5.2.2", "vite": "^5.1.4", + "vite-plugin-node-polyfills": "^0.22.0", "vite-tsconfig-paths": "4.3.2" } }, @@ -1278,10 +1285,11 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.23", @@ -1706,65 +1714,79 @@ } }, "node_modules/@nostr-dev-kit/ndk": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk/-/ndk-2.5.0.tgz", - "integrity": "sha512-A2nRgjjLScDhGZGPWx8xUIJM66dJWScdWQoCn/tI1Gtwpple+C2Jp7C9t3mb0oF3bwd2nsV6qwS//wdrH8QvYQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk/-/ndk-2.10.0.tgz", + "integrity": "sha512-TqCAAo6ylORraAXrzRkCGFN2xTMiFbdER8Y8CtUT0HwOpFG/Wn+PBNeDeDmqkl/6LaPdeyXmVwCWj2KcUjIwYA==", "dependencies": { + "@noble/curves": "^1.4.0", "@noble/hashes": "^1.3.1", "@noble/secp256k1": "^2.0.0", "@scure/base": "^1.1.1", "debug": "^4.3.4", "light-bolt11-decoder": "^3.0.0", "node-fetch": "^3.3.1", - "nostr-tools": "^1.15.0", + "nostr-tools": "^2.7.1", "tseep": "^1.1.1", "typescript-lru-cache": "^2.0.0", "utf8-buffer": "^1.0.0", "websocket-polyfill": "^0.0.3" + }, + "engines": { + "node": ">=16" } }, - "node_modules/@nostr-dev-kit/ndk/node_modules/@noble/ciphers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", - "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==", - "funding": { - "url": "https://paulmillr.com/funding/" + "node_modules/@nostr-dev-kit/ndk-cache-dexie": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk-cache-dexie/-/ndk-cache-dexie-2.5.1.tgz", + "integrity": "sha512-tUwEy68bd9GL5JVuZIjcpdwuDEBnaXen3WJ64/GRDtbyE1RB01Y6hHC7IQC9bcQ6SC7XBGyPd+2nuTyR7+Mffg==", + "dependencies": { + "@nostr-dev-kit/ndk": "2.10.0", + "debug": "^4.3.4", + "dexie": "^4.0.2", + "nostr-tools": "^2.4.0", + "typescript-lru-cache": "^2.0.0" } }, "node_modules/@nostr-dev-kit/ndk/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", + "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", "dependencies": { - "@noble/hashes": "1.3.1" + "@noble/hashes": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@nostr-dev-kit/ndk/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@nostr-dev-kit/ndk/node_modules/nostr-tools": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.17.0.tgz", - "integrity": "sha512-LZmR8GEWKZeElbFV5Xte75dOeE9EFUW/QLI1Ncn3JKn0kFddDKEfBbFN8Mu4TMs+L4HR/WTPha2l+PPuRnJcMw==", + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.10.4.tgz", + "integrity": "sha512-biU7sk+jxHgVASfobg2T5ttxOGGSt69wEVBC51sHHOEaKAAdzHBLV/I2l9Rf61UzClhliZwNouYhqIso4a3HYg==", "dependencies": { - "@noble/ciphers": "0.2.0", - "@noble/curves": "1.1.0", + "@noble/ciphers": "^0.5.1", + "@noble/curves": "1.2.0", "@noble/hashes": "1.3.1", "@scure/base": "1.1.1", "@scure/bip32": "1.3.1", "@scure/bip39": "1.2.1" }, + "optionalDependencies": { + "nostr-wasm": "0.1.0" + }, "peerDependencies": { "typescript": ">=5.0.0" }, @@ -1774,6 +1796,39 @@ } } }, + "node_modules/@nostr-dev-kit/ndk/node_modules/nostr-tools/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nostr-dev-kit/ndk/node_modules/nostr-tools/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@pdf-lib/fontkit": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@pdf-lib/fontkit/-/fontkit-1.1.1.tgz", @@ -1856,6 +1911,52 @@ "node": ">=14.0.0" } }, + "node_modules/@rollup/plugin-inject": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", + "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.22.5", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz", @@ -2160,6 +2261,16 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -2325,6 +2436,17 @@ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, + "node_modules/@types/svgo": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/svgo/-/svgo-3.0.0.tgz", + "integrity": "sha512-G5qLWNq/rMvSM1EyY4E2iEd+s9km/PxLkzPkA2lghrgWJ2jrVMuB1ZsGOzL4YAWCy5sAoUw7SEQseHE2qypF2w==", + "deprecated": "This is a stub types definition. svgo provides its own type definitions, so you do not need this installed.", + "dev": true, + "license": "MIT", + "dependencies": { + "svgo": "*" + } + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", @@ -2730,6 +2852,39 @@ "dev": true, "license": "MIT" }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2744,6 +2899,22 @@ "node": ">=4" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", @@ -2775,6 +2946,27 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "devOptional": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2784,6 +2976,20 @@ "node": ">=8" } }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2805,6 +3011,152 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-rsa/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/browserify-sign": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.5", + "hash-base": "~3.0", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", @@ -2837,6 +3189,38 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" + }, "node_modules/bufferutil": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", @@ -2849,6 +3233,33 @@ "node": ">=6.14.2" } }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2959,6 +3370,23 @@ "node": ">=10" } }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -3110,12 +3538,25 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "devOptional": true }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "optional": true }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "license": "MIT" + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3142,6 +3583,53 @@ "node": ">=10" } }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -3149,10 +3637,11 @@ "dev": true }, "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==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3162,6 +3651,29 @@ "node": ">= 8" } }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, "node_modules/crypto-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/crypto-hash/-/crypto-hash-3.0.0.tgz", @@ -3178,6 +3690,86 @@ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -3246,6 +3838,42 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3260,6 +3888,17 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "optional": true }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", @@ -3269,6 +3908,11 @@ "node": ">=8" } }, + "node_modules/dexie": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.8.tgz", + "integrity": "sha512-1G6cJevS17KMDK847V3OHvK2zei899GwpDiqfEXHP1ASvme6eWJmAp9AU4s1son2TeGkWmC0g3y8ezOBPnalgQ==" + }, "node_modules/dezalgo": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", @@ -3289,6 +3933,25 @@ "node": ">=0.3.1" } }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3353,18 +4016,126 @@ "csstype": "^3.0.2" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domain-browser": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.23.0.tgz", + "integrity": "sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.682", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.682.tgz", "integrity": "sha512-oCglfs8yYKs9RQjJFOHonSnhikPK3y+0SvSYc/YpYJV//6rqc0/hbwd0c7vgK4vrl6y2gJAwjkhkSGWK+z4KRA==", "dev": true }, + "node_modules/elliptic": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "optional": true }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/environment": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", @@ -3386,6 +4157,29 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es5-ext": { "version": "0.10.63", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.63.tgz", @@ -3768,6 +4562,13 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3793,6 +4594,27 @@ "dev": true, "license": "MIT" }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -4026,6 +4848,16 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -4151,6 +4983,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -4253,6 +5105,19 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4274,12 +5139,92 @@ "node": ">=4" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "optional": true }, + "node_modules/hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", @@ -4291,6 +5236,18 @@ "node": ">= 0.4" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -4311,6 +5268,13 @@ "dev": true, "license": "ISC" }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "license": "MIT" + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -4339,6 +5303,27 @@ "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz", "integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==" }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -4407,6 +5392,23 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4424,6 +5426,19 @@ "node": ">=8" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -4453,6 +5468,22 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4465,6 +5496,23 @@ "node": ">=0.10.0" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -4496,6 +5544,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -4512,6 +5576,16 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4925,6 +5999,16 @@ "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4955,6 +6039,45 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/material-ui-popup-state": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/material-ui-popup-state/-/material-ui-popup-state-5.3.1.tgz", + "integrity": "sha512-mmx1DsQwF/2cmcpHvS/QkUwOQG2oAM+cDEQU0DaZVYnvwKyTB3AFgu8l1/E+LQFausmzpSJoljwQSZXkNvt7eA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.6", + "@types/prop-types": "^15.7.3", + "@types/react": "^18.0.26", + "classnames": "^2.2.6", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@mui/material": "^5.0.0 || ^6.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4985,6 +6108,27 @@ "node": ">=8.6" } }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -5042,6 +6186,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "license": "MIT" + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -5152,9 +6310,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -5162,6 +6320,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5231,6 +6390,67 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/node-stdlib-browser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.2.1.tgz", + "integrity": "sha512-dZezG3D88Lg22DwyjsDuUs7cCT/XGr8WwJgg/S3ZnkcWuPet2Tt/W1d2Eytb1Z73JpZv+XVCDI5TWv6UMRq0Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.11.0", + "domain-browser": "^4.22.0", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-stdlib-browser/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -5279,9 +6499,9 @@ } }, "node_modules/nostr-login": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/nostr-login/-/nostr-login-1.6.6.tgz", - "integrity": "sha512-XOpB9nG3Qgt7iea7gA1zn4TaTfUKCKGdCHKwErqLPtMk/q1Rhkzj5cq/66iU0WqC6mSiwENfTy1p4qaM7HzMtg==", + "version": "1.6.14", + "resolved": "https://registry.npmjs.org/nostr-login/-/nostr-login-1.6.14.tgz", + "integrity": "sha512-pId1G79kjRW1B9qy6OrA8Not23JSfgmS2VegcKf7Qm9VMC7wYGXg1Ry3FMEAB8p11WoboQ8oJi2TqUGiOf61OQ==", "license": "MIT", "dependencies": { "@nostr-dev-kit/ndk": "^2.3.1", @@ -5434,6 +6654,19 @@ "set-blocking": "^2.0.0" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5442,6 +6675,65 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5484,6 +6776,13 @@ "node": ">= 0.8.0" } }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "license": "MIT" + }, "node_modules/os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -5562,6 +6861,45 @@ "node": ">=6" } }, + "node_modules/parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-asn1/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -5579,6 +6917,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5628,6 +6973,23 @@ "node": ">=6" } }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/pdf-lib": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", @@ -5684,6 +7046,29 @@ "node": ">=0.10" } }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", @@ -5767,6 +7152,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -5792,6 +7187,28 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5801,6 +7218,31 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5821,6 +7263,27 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "node_modules/rdndmb-html5-to-touch": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/rdndmb-html5-to-touch/-/rdndmb-html5-to-touch-8.0.3.tgz", @@ -6281,6 +7744,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/rollup": { "version": "4.22.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", @@ -6409,11 +7883,43 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "optional": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6435,12 +7941,37 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "optional": true }, + "node_modules/signature_pad": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/signature_pad/-/signature_pad-5.0.4.tgz", + "integrity": "sha512-nngOixbwLAUOuH3QnZwlgwmynQblxmo4iWacKFwfymJfiY+Qt+9icNtcIe/okqXKun4hJ5QTFmHyC7dmv6lf2w==", + "license": "MIT" + }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -6619,6 +8150,60 @@ "spdx-ranges": "^2.0.0" } }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -6715,6 +8300,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -6744,6 +8365,19 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -6882,6 +8516,13 @@ "resolved": "https://registry.npmjs.org/tstl/-/tstl-2.5.13.tgz", "integrity": "sha512-h9wayHHFI5+yqt8iau0vqH96cTNhezhZ/Fk/hrIdpfkiMu3lg9nzyvMfs5bIdX51IVzZO6DudLqhkL/rVXpT6g==" }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "license": "MIT" + }, "node_modules/type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -6984,6 +8625,37 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/use-immer": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/use-immer/-/use-immer-0.11.0.tgz", + "integrity": "sha512-RNAqi3GqsWJ4bcCd4LMBgdzvPmTABam24DUaFiKfX9s3MSorNRz9RDZYJkllJoMHUxVLMDetwAuCDeyWNrp1yA==", + "license": "MIT", + "peerDependencies": { + "immer": ">=8.0.0", + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -7012,6 +8684,20 @@ "node": ">=8" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7101,6 +8787,23 @@ } } }, + "node_modules/vite-plugin-node-polyfills": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz", + "integrity": "sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-inject": "^5.0.5", + "node-stdlib-browser": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/davidmyersdev" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, "node_modules/vite-tsconfig-paths": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz", @@ -7120,6 +8823,13 @@ } } }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "license": "MIT" + }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", @@ -7197,6 +8907,26 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -7297,6 +9027,16 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "devOptional": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", diff --git a/package.json b/package.json index 6cedc9b..98bc510 100644 --- a/package.json +++ b/package.json @@ -30,19 +30,22 @@ "@mui/lab": "5.0.0-alpha.166", "@mui/material": "5.15.11", "@noble/hashes": "^1.4.0", - "@nostr-dev-kit/ndk": "2.5.0", + "@nostr-dev-kit/ndk": "2.10.0", + "@nostr-dev-kit/ndk-cache-dexie": "2.5.1", "@pdf-lib/fontkit": "^1.1.1", "@reduxjs/toolkit": "2.2.1", "axios": "^1.7.4", "crypto-hash": "3.0.0", "crypto-js": "^4.2.0", + "dexie": "4.0.8", "dnd-core": "16.0.1", "file-saver": "2.0.5", "idb": "8.0.0", "jszip": "3.10.1", "lodash": "4.17.21", + "material-ui-popup-state": "^5.3.1", "mui-file-input": "4.0.4", - "nostr-login": "^1.6.6", + "nostr-login": "1.6.14", "nostr-tools": "2.7.0", "pdf-lib": "^1.17.1", "pdfjs-dist": "^4.4.168", @@ -57,7 +60,9 @@ "react-singleton-hook": "^4.0.1", "react-toastify": "10.0.4", "redux": "5.0.1", - "tseep": "1.2.1" + "signature_pad": "^5.0.4", + "tseep": "1.2.1", + "use-immer": "^0.11.0" }, "devDependencies": { "@types/crypto-js": "^4.2.2", @@ -66,6 +71,7 @@ "@types/pdfjs-dist": "^2.10.378", "@types/react": "^18.2.56", "@types/react-dom": "^18.2.19", + "@types/svgo": "^3.0.0", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", "@vitejs/plugin-react": "^4.2.1", @@ -78,6 +84,7 @@ "ts-css-modules-vite-plugin": "1.0.20", "typescript": "^5.2.2", "vite": "^5.1.4", + "vite-plugin-node-polyfills": "^0.22.0", "vite-tsconfig-paths": "4.3.2" }, "lint-staged": { diff --git a/public/.well-known/nostr.json b/public/.well-known/nostr.json index 6dd4dd9..f40a176 100644 --- a/public/.well-known/nostr.json +++ b/public/.well-known/nostr.json @@ -1,15 +1,15 @@ { - "names": { - "_": "6bf1024c6336093b632db2da21b65a44c7d82830454fb4d75634ba281e161c90" - }, - "relays": { - "6bf1024c6336093b632db2da21b65a44c7d82830454fb4d75634ba281e161c90": [ - "wss://brb.io", - "wss://nostr.v0l.io", - "wss://nostr.coinos.io", - "wss://rsslay.nostr.net", - "wss://relay.current.fyi", - "wss://nos.io" - ] - } + "names": { + "_": "6bf1024c6336093b632db2da21b65a44c7d82830454fb4d75634ba281e161c90" + }, + "relays": { + "6bf1024c6336093b632db2da21b65a44c7d82830454fb4d75634ba281e161c90": [ + "wss://brb.io", + "wss://nostr.v0l.io", + "wss://nostr.coinos.io", + "wss://rsslay.nostr.net", + "wss://relay.current.fyi", + "wss://nos.io" + ] + } } \ No newline at end of file diff --git a/public/opentimestamps.min.js b/public/opentimestamps.min.js new file mode 100644 index 0000000..f23302d --- /dev/null +++ b/public/opentimestamps.min.js @@ -0,0 +1,2 @@ +// opentimestamps v.0.4.9 +function _get(e,t,r){return(_get="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,r){e=_superPropBase(e,t);if(e){t=Object.getOwnPropertyDescriptor(e,t);return t.get?t.get.call(r):t.value}})(e,t,r||e)}function _superPropBase(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=_getPrototypeOf(e)););return e}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_setPrototypeOf(e,t)}function _createSuper(r){var i=_isNativeReflectConstruct();return function(){var e,t=_getPrototypeOf(r);return _possibleConstructorReturn(this,i?(e=_getPrototypeOf(this).constructor,Reflect.construct(t,arguments,e)):t.apply(this,arguments))}}function _possibleConstructorReturn(e,t){return!t||"object"!==_typeof(t)&&"function"!=typeof t?_assertThisInitialized(e):t}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _getPrototypeOf(e){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_unsupportedIterableToArray(e)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _iterableToArray(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}function _arrayWithoutHoles(e){if(Array.isArray(e))return _arrayLikeToArray(e)}function _classCallCheck2(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var r=0;r=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:t}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n,a=!0,o=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return a=e.done,e},e:function(e){o=!0,n=e},f:function(){try{a||null==r.return||r.return()}finally{if(o)throw n}}}}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Map"===(r="Object"===r&&e.constructor?e.constructor.name:r)||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,i=new Array(t);r%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,f=/^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-)*(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-)*(?:[0-9a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[a-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i,p=/^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,l=/^(?:\/(?:[^~/]|~0|~1)*)*$/,h=/^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,e=/^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;function d(e){return e="full"==e?"full":"fast",i.copy(d[e])}function m(e){var t=e.match(n);if(!t)return!1;var r=+t[1],e=+t[2],t=+t[3];return 1<=e&&e<=12&&1<=t&&t<=(2!=e||((r=r)%4!=0||r%100==0&&r%400!=0)?a[e]:29)}function g(e,t){var r=e.match(o);if(!r)return!1;var i=r[1],n=r[2],e=r[3],r=r[5];return(i<=23&&n<=59&&e<=59||23==i&&59==n&&60==e)&&(!t||r)}(t.exports=d).fast={date:/^\d\d\d\d-[0-1]\d-[0-3]\d$/,time:/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i,"date-time":/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i,uri:/^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i,"uri-reference":/^(?:(?:[a-z][a-z0-9+\-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,"uri-template":c,url:f,email:/^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,hostname:s,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:_,uuid:p,"json-pointer":l,"json-pointer-uri-fragment":h,"relative-json-pointer":e},d.full={date:m,time:g,"date-time":function(e){e=e.split(b);return 2==e.length&&m(e[0])&&g(e[1],!0)},uri:function(e){return y.test(e)&&u.test(e)},"uri-reference":/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,"uri-template":c,url:f,email:/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,hostname:s,ipv4:/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,ipv6:/^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,regex:_,uuid:p,"json-pointer":l,"json-pointer-uri-fragment":h,"relative-json-pointer":e};var b=/t|\s/i;var y=/\/|:/;var v=/[^\\]\\Z/;function _(e){if(v.test(e))return!1;try{return new RegExp(e),!0}catch(e){return!1}}},{"./util":12}],7:[function(e,t,r){"use strict";var A=e("./resolve"),P=e("./util"),I=e("./error_classes"),T=e("fast-json-stable-stringify"),O=e("../dotjs/validate"),C=P.ucs2length,R=e("fast-deep-equal"),B=I.Validation;function F(e,s,u,t){var c=this,f=this._opts,p=[void 0],l={},h=[],r={},d=[],i={},m=[],n=function(e,t,r){var i=M.call(this,e,t,r);return 0<=i?{index:i,compiling:!0}:(i=this._compilations.length,this._compilations[i]={schema:e,root:t,baseId:r},{index:i,compiling:!1})}.call(this,e,s=s||{schema:e,refVal:p,refs:l},t),a=this._compilations[n.index];if(n.compiling)return a.callValidate=v;var g=this._formats,b=this.RULES;try{var o=_(e,s,u,t);a.validate=o;var y=a.callValidate;return y&&(y.schema=o.schema,y.errors=null,y.refs=o.refs,y.refVal=o.refVal,y.root=o.root,y.$async=o.$async,f.sourceCode&&(y.source=o.source)),o}finally{(function(e,t,r){r=M.call(this,e,t,r);0<=r&&this._compilations.splice(r,1)}).call(this,e,s,t)}function v(){var e=a.validate,t=e.apply(this,arguments);return v.errors=e.errors,t}function _(e,t,r,i){var n=!t||t&&t.schema==e;if(t.schema!=s.schema)return F.call(c,e,t,r,i);var r=!0===e.$async,a=O({isTop:!0,schema:e,isRoot:n,baseId:i,root:t,schemaPath:"",errSchemaPath:"#",errorPath:'""',MissingRefError:I.MissingRef,RULES:b,validate:O,util:P,resolve:A,resolveRef:w,usePattern:S,useDefault:j,useCustomRule:E,opts:f,formats:g,logger:c.logger,self:c}),a=q(p,D)+q(h,z)+q(d,N)+q(m,L)+a;f.processCode&&(a=f.processCode(a,e));try{var o=new Function("self","RULES","formats","root","refVal","defaults","customRules","equal","ucs2length","ValidationError",a)(c,b,g,s,p,d,m,R,C,B);p[0]=o}catch(e){throw c.logger.error("Error compiling schema, function code:",a),e}return o.schema=e,o.errors=null,o.refs=l,o.refVal=p,o.root=n?o:t,r&&(o.$async=!0),!0===f.sourceCode&&(o.source={code:a,patterns:h,defaults:d}),o}function w(e,t,r){t=A.url(e,t);var i,n=l[t];if(void 0!==n)return x(o=p[n],i="refVal["+n+"]");if(!r&&s.refs){var a=s.refs[t];if(void 0!==a)return x(o=s.refVal[a],i=k(t,o))}i=k(t);var o,a=A.call(c,_,s,t);if(void 0!==a||(o=u&&u[t])&&(a=A.inlineRef(o,f.inlineRefs)?o:F.call(c,o,s,u,e)),void 0!==a)return e=l[e=t],x(p[e]=a,i);delete l[t]}function k(e,t){var r=p.length;return p[r]=t,"refVal"+(l[e]=r)}function x(e,t){return"object"==_typeof(e)||"boolean"==typeof e?{code:t,schema:e,inline:!0}:{code:t,$async:e&&!!e.$async}}function S(e){var t=r[e];return void 0===t&&(t=r[e]=h.length,h[t]=e),"pattern"+t}function j(e){switch(_typeof(e)){case"boolean":case"number":return""+e;case"string":return P.toQuotedString(e);case"object":if(null===e)return"null";var t=T(e),r=i[t];return void 0===r&&(r=i[t]=d.length,d[r]=e),"default"+r}}function E(e,t,r,i){if(!1!==c._opts.validateSchema){var n=e.definition.dependencies;if(n&&!n.every(function(e){return Object.prototype.hasOwnProperty.call(r,e)}))throw new Error("parent schema must have all required keywords: "+n.join(","));var a=e.definition.validateSchema;if(a)if(!a(t)){var o="keyword schema is invalid: "+c.errorsText(a.errors);if("log"!=c._opts.validateSchema)throw new Error(o);c.logger.error(o)}}var s,n=e.definition.compile,a=e.definition.inline,o=e.definition.macro;if(n)s=n.call(c,t,r,i);else if(o)s=o.call(c,t,r,i),!1!==f.validateSchema&&c.validateSchema(s,!0);else if(a)s=a.call(c,i,e.keyword,t,r);else if(!(s=e.definition.validate))return;if(void 0===s)throw new Error('custom keyword "'+e.keyword+'"failed to compile');e=m.length;return{code:"customRule"+e,validate:m[e]=s}}}function M(e,t,r){for(var i=0;i",S=v?">":"<",j=void 0;if(!b&&"number"!=typeof l&&void 0!==l)throw new Error(t+" must be number");if(!k&&void 0!==w&&"number"!=typeof w&&"boolean"!=typeof w)throw new Error(_+" must be number or boolean");k?(a="exclIsNumber"+f,o="' + "+(s="op"+f)+" + '",c+=" var schemaExcl"+f+" = "+(i=e.util.getData(w.$data,p,e.dataPathArr))+"; ",j=_,(u=u||[]).push(c+=" var "+(n="exclusive"+f)+"; var "+(p="exclType"+f)+" = typeof "+(i="schemaExcl"+f)+"; if ("+p+" != 'boolean' && "+p+" != 'undefined' && "+p+" != 'number') { "),c="",!1!==e.createErrors?(c+=" { keyword: '"+(j||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(d)+" , params: {} ",!1!==e.opts.messages&&(c+=" , message: '"+_+" should be boolean' "),e.opts.verbose&&(c+=" , schema: validate.schema"+h+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+g+" "),c+=" } "):c+=" {} ",E=c,c=u.pop(),!e.compositeRule&&m?e.async?c+=" throw new ValidationError(["+E+"]); ":c+=" validate.errors = ["+E+"]; return false; ":c+=" var err = "+E+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",c+=" } else if ( ",b&&(c+=" ("+y+" !== undefined && typeof "+y+" != 'number') || "),c+=" "+p+" == 'number' ? ( ("+n+" = "+y+" === undefined || "+i+" "+x+"= "+y+") ? "+g+" "+S+"= "+i+" : "+g+" "+S+" "+y+" ) : ( ("+n+" = "+i+" === true) ? "+g+" "+S+"= "+y+" : "+g+" "+S+" "+y+" ) || "+g+" !== "+g+") { var op"+f+" = "+n+" ? '"+x+"' : '"+x+"='; ",void 0===l&&(j=_,d=e.errSchemaPath+"/"+_,y=i,b=k)):(o=x,(a="number"==typeof w)&&b?(s="'"+o+"'",c+=" if ( ",b&&(c+=" ("+y+" !== undefined && typeof "+y+" != 'number') || "),c+=" ( "+y+" === undefined || "+w+" "+x+"= "+y+" ? "+g+" "+S+"= "+w+" : "+g+" "+S+" "+y+" ) || "+g+" !== "+g+") { "):(a&&void 0===l?(n=!0,j=_,d=e.errSchemaPath+"/"+_,y=w,S+="="):(a&&(y=Math[v?"min":"max"](w,l)),w===(!a||y)?(n=!0,j=_,d=e.errSchemaPath+"/"+_,S+="="):(n=!1,o+="=")),s="'"+o+"'",c+=" if ( ",b&&(c+=" ("+y+" !== undefined && typeof "+y+" != 'number') || "),c+=" "+g+" "+S+" "+y+" || "+g+" !== "+g+") { ")),j=j||t,(u=u||[]).push(c),c="",!1!==e.createErrors?(c+=" { keyword: '"+(j||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(d)+" , params: { comparison: "+s+", limit: "+y+", exclusive: "+n+" } ",!1!==e.opts.messages&&(c+=" , message: 'should be "+o+" ",c+=b?"' + "+y:y+"'"),e.opts.verbose&&(c+=" , schema: ",c+=b?"validate.schema"+h:""+l,c+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+g+" "),c+=" } "):c+=" {} ";var E=c;return c=u.pop(),!e.compositeRule&&m?e.async?c+=" throw new ValidationError(["+E+"]); ":c+=" validate.errors = ["+E+"]; return false; ":c+=" var err = "+E+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",c+=" } ",m&&(c+=" else { "),c}},{}],16:[function(e,t,r){"use strict";t.exports=function(e,t,r){var i=" ",n=e.level,a=e.dataLevel,o=e.schema[t],s=e.schemaPath+e.util.getProperty(t),u=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,f="data"+(a||""),p=e.opts.$data&&o&&o.$data,a=p?(i+=" var schema"+n+" = "+e.util.getData(o.$data,a,e.dataPathArr)+"; ","schema"+n):o;if(!p&&"number"!=typeof o)throw new Error(t+" must be number");i+="if ( ",p&&(i+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),i+=" "+f+".length "+("maxItems"==t?">":"<")+" "+a+") { ";var n=t,l=l||[];l.push(i),i="",!1!==e.createErrors?(i+=" { keyword: '"+(n||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(u)+" , params: { limit: "+a+" } ",!1!==e.opts.messages&&(i+=" , message: 'should NOT have ",i+="maxItems"==t?"more":"fewer",i+=" than ",i+=p?"' + "+a+" + '":""+o,i+=" items' "),e.opts.verbose&&(i+=" , schema: ",i+=p?"validate.schema"+s:""+o,i+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+f+" "),i+=" } "):i+=" {} ";f=i,i=l.pop();return!e.compositeRule&&c?e.async?i+=" throw new ValidationError(["+f+"]); ":i+=" validate.errors = ["+f+"]; return false; ":i+=" var err = "+f+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",i+="} ",c&&(i+=" else { "),i}},{}],17:[function(e,t,r){"use strict";t.exports=function(e,t,r){var i=" ",n=e.level,a=e.dataLevel,o=e.schema[t],s=e.schemaPath+e.util.getProperty(t),u=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,f="data"+(a||""),p=e.opts.$data&&o&&o.$data,a=p?(i+=" var schema"+n+" = "+e.util.getData(o.$data,a,e.dataPathArr)+"; ","schema"+n):o;if(!p&&"number"!=typeof o)throw new Error(t+" must be number");var n="maxLength"==t?">":"<";i+="if ( ",p&&(i+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),!1===e.opts.unicode?i+=" "+f+".length ":i+=" ucs2length("+f+") ",i+=" "+n+" "+a+") { ";var n=t,l=l||[];l.push(i),i="",!1!==e.createErrors?(i+=" { keyword: '"+(n||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(u)+" , params: { limit: "+a+" } ",!1!==e.opts.messages&&(i+=" , message: 'should NOT be ",i+="maxLength"==t?"longer":"shorter",i+=" than ",i+=p?"' + "+a+" + '":""+o,i+=" characters' "),e.opts.verbose&&(i+=" , schema: ",i+=p?"validate.schema"+s:""+o,i+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+f+" "),i+=" } "):i+=" {} ";f=i,i=l.pop();return!e.compositeRule&&c?e.async?i+=" throw new ValidationError(["+f+"]); ":i+=" validate.errors = ["+f+"]; return false; ":i+=" var err = "+f+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",i+="} ",c&&(i+=" else { "),i}},{}],18:[function(e,t,r){"use strict";t.exports=function(e,t,r){var i=" ",n=e.level,a=e.dataLevel,o=e.schema[t],s=e.schemaPath+e.util.getProperty(t),u=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,f="data"+(a||""),p=e.opts.$data&&o&&o.$data,a=p?(i+=" var schema"+n+" = "+e.util.getData(o.$data,a,e.dataPathArr)+"; ","schema"+n):o;if(!p&&"number"!=typeof o)throw new Error(t+" must be number");i+="if ( ",p&&(i+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),i+=" Object.keys("+f+").length "+("maxProperties"==t?">":"<")+" "+a+") { ";var n=t,l=l||[];l.push(i),i="",!1!==e.createErrors?(i+=" { keyword: '"+(n||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(u)+" , params: { limit: "+a+" } ",!1!==e.opts.messages&&(i+=" , message: 'should NOT have ",i+="maxProperties"==t?"more":"fewer",i+=" than ",i+=p?"' + "+a+" + '":""+o,i+=" properties' "),e.opts.verbose&&(i+=" , schema: ",i+=p?"validate.schema"+s:""+o,i+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+f+" "),i+=" } "):i+=" {} ";f=i,i=l.pop();return!e.compositeRule&&c?e.async?i+=" throw new ValidationError(["+f+"]); ":i+=" validate.errors = ["+f+"]; return false; ":i+=" var err = "+f+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",i+="} ",c&&(i+=" else { "),i}},{}],19:[function(e,t,r){"use strict";t.exports=function(e,t,r){var i=" ",n=e.schema[t],a=e.schemaPath+e.util.getProperty(t),o=e.errSchemaPath+"/"+t,s=!e.opts.allErrors,u=e.util.copy(e),c="";u.level++;var f="valid"+u.level,p=u.baseId,l=!0,h=n;if(h)for(var d,m=-1,g=h.length-1;m "+w+") { ",x=f+"["+w+"]",h.schema=j,h.schemaPath=s+"["+w+"]",h.errSchemaPath=u+"/"+w,h.errorPath=e.util.getPathExpr(e.errorPath,w,e.opts.jsonPointers,!0),h.dataPathArr[g]=w,S=e.validate(h),h.baseId=y,e.util.varOccurences(S,b)<2?i+=" "+e.util.varReplace(S,b,x)+" ":i+=" var "+b+" = "+x+"; "+S+" ",i+=" } ",c&&(i+=" if ("+m+") { ",d+="}"))}"object"==_typeof(a)&&(e.opts.strictKeywords?"object"==_typeof(a)&&0 "+o.length+") { for (var "+t+" = "+o.length+"; "+t+" < "+f+".length; "+t+"++) { ",h.errorPath=e.util.getPathExpr(e.errorPath,t,e.opts.jsonPointers,!0),x=f+"["+t+"]",h.dataPathArr[g]=t,S=e.validate(h),h.baseId=y,e.util.varOccurences(S,b)<2?i+=" "+e.util.varReplace(S,b,x)+" ":i+=" var "+b+" = "+x+"; "+S+" ",c&&(i+=" if (!"+m+") break; "),i+=" } } ",c&&(i+=" if ("+m+") { ",d+="}"))}else(e.opts.strictKeywords?"object"==_typeof(o)&&0 1e-"+e.opts.multipleOfPrecision+" ":i+=" division"+n+" !== parseInt(division"+n+") ",i+=" ) ",p&&(i+=" ) "),i+=" ) { ";var l=l||[];l.push(i),i="",!1!==e.createErrors?(i+=" { keyword: 'multipleOf' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(u)+" , params: { multipleOf: "+a+" } ",!1!==e.opts.messages&&(i+=" , message: 'should be multiple of ",i+=p?"' + "+a:a+"'"),e.opts.verbose&&(i+=" , schema: ",i+=p?"validate.schema"+s:""+o,i+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+f+" "),i+=" } "):i+=" {} ";f=i,i=l.pop();return!e.compositeRule&&c?e.async?i+=" throw new ValidationError(["+f+"]); ":i+=" validate.errors = ["+f+"]; return false; ":i+=" var err = "+f+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",i+="} ",c&&(i+=" else { "),i}},{}],32:[function(e,t,r){"use strict";t.exports=function(e,t,r){var i=" ",n=e.level,a=e.dataLevel,o=e.schema[t],s=e.schemaPath+e.util.getProperty(t),u=e.errSchemaPath+"/"+t,c=!e.opts.allErrors,f="data"+(a||""),t="errs__"+n,a=e.util.copy(e);a.level++;var p,l,n="valid"+a.level;return(e.opts.strictKeywords?"object"==_typeof(o)&&0=e.opts.loopRequired,v=e.opts.ownProperties;if(c)if(i+=" var missing"+n+"; ",o){t||(i+=" var "+a+" = validate.schema"+s+"; ");var _="' + "+(E="schema"+n+"["+(x="i"+n)+"]")+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(y,E,e.opts.jsonPointers)),i+=" var "+p+" = true; ",t&&(i+=" if (schema"+n+" === undefined) "+p+" = true; else if (!Array.isArray(schema"+n+")) "+p+" = false; else {"),i+=" for (var "+x+" = 0; "+x+" < "+a+".length; "+x+"++) { "+p+" = "+f+"["+a+"["+x+"]] !== undefined ",v&&(i+=" && Object.prototype.hasOwnProperty.call("+f+", "+a+"["+x+"]) "),i+="; if (!"+p+") break; } ",t&&(i+=" } "),(j=j||[]).push(i+=" if (!"+p+") { "),i="",!1!==e.createErrors?(i+=" { keyword: 'required' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(u)+" , params: { missingProperty: '"+_+"' } ",!1!==e.opts.messages&&(i+=" , message: '",e.opts._errorDataPathProperty?i+="is a required property":i+="should have required property \\'"+_+"\\'",i+="' "),e.opts.verbose&&(i+=" , schema: validate.schema"+s+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+f+" "),i+=" } "):i+=" {} ";var w=i,i=j.pop();!e.compositeRule&&c?e.async?i+=" throw new ValidationError(["+w+"]); ":i+=" validate.errors = ["+w+"]; return false; ":i+=" var err = "+w+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",i+=" } else { "}else{i+=" if ( ";var k=l;if(k)for(var x=-1,S=k.length-1;x 1) { ",o=e.schema.items&&e.schema.items.type,a=Array.isArray(o),!o||"object"==o||"array"==o||a&&(0<=o.indexOf("object")||0<=o.indexOf("array"))?n+=" outer: for (;i--;) { for (j = i; j--;) { if (equal("+p+"[i], "+p+"[j])) { "+l+" = false; break outer; } } } ":(n+=" var itemIndices = {}, item; for (;i--;) { var item = "+p+"[i]; ",t="checkDataType"+(a?"s":""),n+=" if ("+e.util[t](o,"item",e.opts.strictNumbers,!0)+") continue; ",a&&(n+=" if (typeof item == 'string') item = '\"' + item; "),n+=" if (typeof itemIndices[item] == 'number') { "+l+" = false; j = itemIndices[item]; break; } itemIndices[item] = i; } "),n+=" } ",h&&(n+=" } "),(i=i||[]).push(n+=" if (!"+l+") { "),n="",!1!==e.createErrors?(n+=" { keyword: 'uniqueItems' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { i: i, j: j } ",!1!==e.opts.messages&&(n+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(n+=" , schema: ",n+=h?"validate.schema"+u:""+s,n+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+p+" "),n+=" } "):n+=" {} ",p=n,n=i.pop(),!e.compositeRule&&f?e.async?n+=" throw new ValidationError(["+p+"]); ":n+=" validate.errors = ["+p+"]; return false; ":n+=" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",n+=" } ",f&&(n+=" else { ")):f&&(n+=" if (true) { "),n}},{}],40:[function(e,t,r){"use strict";t.exports=function(i,e,t){var r="",n=!0===i.schema.$async,a=i.util.schemaHasRulesExcept(i.schema,i.RULES.all,"$ref"),o=i.self._getId(i.schema);if(i.opts.strictKeywords){var s=i.util.schemaUnknownRules(i.schema,i.RULES.keywords);if(s){s="unknown keyword: "+s;if("log"!==i.opts.strictKeywords)throw new Error(s);i.logger.warn(s)}}if(i.isTop&&(r+=" var validate = ",n&&(i.async=!0,r+="async "),r+="function(data, dataPath, parentData, parentDataProperty, rootData) { 'use strict'; ",o&&(i.opts.sourceCode||i.opts.processCode)&&(r+=" /*# sourceURL="+o+" */ ")),"boolean"==typeof i.schema||!a&&!i.schema.$ref){var e="false schema",u=i.level,c=i.dataLevel,f=i.schema[e],p=i.schemaPath+i.util.getProperty(e),l=i.errSchemaPath+"/"+e,h=!i.opts.allErrors,d="data"+(c||""),m="valid"+u;return!1===i.schema?(i.isTop?h=!0:r+=" var "+m+" = false; ",(U=U||[]).push(r),r="",!1!==i.createErrors?(r+=" { keyword: 'false schema' , dataPath: (dataPath || '') + "+i.errorPath+" , schemaPath: "+i.util.toQuotedString(l)+" , params: {} ",!1!==i.opts.messages&&(r+=" , message: 'boolean schema is false' "),i.opts.verbose&&(r+=" , schema: false , parentSchema: validate.schema"+i.schemaPath+" , data: "+d+" "),r+=" } "):r+=" {} ",T=r,r=U.pop(),!i.compositeRule&&h?i.async?r+=" throw new ValidationError(["+T+"]); ":r+=" validate.errors = ["+T+"]; return false; ":r+=" var err = "+T+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; "):i.isTop?r+=n?" return data; ":" validate.errors = null; return true; ":r+=" var "+m+" = true; ",i.isTop&&(r+=" }; return validate; "),r}if(i.isTop){var g=i.isTop,u=i.level=0,c=i.dataLevel=0,d="data";if(i.rootId=i.resolve.fullPath(i.self._getId(i.root.schema)),i.baseId=i.baseId||i.rootId,delete i.isTop,i.dataPathArr=[""],void 0!==i.schema.default&&i.opts.useDefaults&&i.opts.strictDefaults){var b="default is ignored in the schema root";if("log"!==i.opts.strictDefaults)throw new Error(b);i.logger.warn(b)}r+=" var vErrors = null; ",r+=" var errors = 0; ",r+=" if (rootData === undefined) rootData = data; "}else{u=i.level,d="data"+((c=i.dataLevel)||"");if(o&&(i.baseId=i.resolve.url(i.baseId,o)),n&&!i.async)throw new Error("async schema in sync schema");r+=" var errs_"+u+" = errors;"}var y,m="valid"+u,h=!i.opts.allErrors,v="",_="",w=i.schema.type,k=Array.isArray(w);if(w&&i.opts.nullable&&!0===i.schema.nullable&&(k?-1==w.indexOf("null")&&(w=w.concat("null")):"null"!=w&&(w=[w,"null"],k=!0)),k&&1==w.length&&(w=w[0],k=!1),i.schema.$ref&&a){if("fail"==i.opts.extendRefs)throw new Error('$ref: validation keywords used in schema at path "'+i.errSchemaPath+'" (see option extendRefs)');!0!==i.opts.extendRefs&&(a=!1,i.logger.warn('$ref: keywords ignored in schema at path "'+i.errSchemaPath+'"'))}if(i.schema.$comment&&i.opts.$comment&&(r+=" "+i.RULES.all.$comment.code(i,"$comment")),w){i.opts.coerceTypes&&(y=i.util.coerceToTypes(i.opts.coerceTypes,w));var x=i.RULES.types[w];if(y||k||!0===x||x&&!G(x)){p=i.schemaPath+".type",l=i.errSchemaPath+"/type",p=i.schemaPath+".type",l=i.errSchemaPath+"/type",o=k?"checkDataTypes":"checkDataType";if(r+=" if ("+i.util[o](w,d,i.opts.strictNumbers,!0)+") { ",y){var S="dataType"+u,j="coerced"+u;r+=" var "+S+" = typeof "+d+"; var "+j+" = undefined; ","array"==i.opts.coerceTypes&&(r+=" if ("+S+" == 'object' && Array.isArray("+d+") && "+d+".length == 1) { "+d+" = "+d+"[0]; "+S+" = typeof "+d+"; if ("+i.util.checkDataType(i.schema.type,d,i.opts.strictNumbers)+") "+j+" = "+d+"; } "),r+=" if ("+j+" !== undefined) ; ";var E=y;if(E)for(var A,P=-1,I=E.length-1;P>6],n=0==(32&r);if(31==(31&r))for(var a=r,r=0;128==(128&a);){if(a=e.readUInt8(t),e.isError(a))return a;r<<=7,r|=127&a}else r&=31;return{cls:i,primitive:n,tag:r,tagStr:s.tag[r]}}function p(e,t,r){var i=e.readUInt8(r);if(e.isError(i))return i;if(!t&&128===i)return null;if(0==(128&i))return i;var n=127&i;if(4>=8)n++;var o=l.alloc(2+n);o[0]=t,o[1]=128|n;for(var s=1+n,u=i.length;0>=8)o[s]=255&u;return this._createEncoderBuffer([o,i])},o.prototype._encodeStr=function(e,t){if("bitstr"===t)return this._createEncoderBuffer([0|e.unused,e.data]);if("bmpstr"!==t)return"numstr"===t?this._isNumstr(e)?this._createEncoderBuffer(e):this.reporter.error("Encoding of string type: numstr supports only digits and space"):"printstr"===t?this._isPrintstr(e)?this._createEncoderBuffer(e):this.reporter.error("Encoding of string type: printstr supports only latin upper and lower case letters, digits, space, apostrophe, left and rigth parenthesis, plus sign, comma, hyphen, dot, slash, colon, equal sign, question mark"):/str$/.test(t)||"objDesc"===t?this._createEncoderBuffer(e):this.reporter.error("Encoding of string type: "+t+" unsupported");for(var r=l.alloc(2*e.length),i=0;i>=7)a++}for(var u=l.alloc(a),c=u.length-1,f=e.length-1;0<=f;f--){var p=e[f];for(u[c--]=127&p;0<(p>>=7);)u[c--]=128|127&p}return this._createEncoderBuffer(u)},o.prototype._encodeTime=function(e,t){var r,e=new Date(e);return"gentime"===t?r=[s(e.getUTCFullYear()),s(e.getUTCMonth()+1),s(e.getUTCDate()),s(e.getUTCHours()),s(e.getUTCMinutes()),s(e.getUTCSeconds()),"Z"].join(""):"utctime"===t?r=[s(e.getUTCFullYear()%100),s(e.getUTCMonth()+1),s(e.getUTCDate()),s(e.getUTCHours()),s(e.getUTCMinutes()),s(e.getUTCSeconds()),"Z"].join(""):this.reporter.error("Encoding "+t+" time is not supported yet"),this._encodeStr(r,"octstr")},o.prototype._encodeNull=function(){return this._createEncoderBuffer("")},o.prototype._encodeInt=function(e,t){if("string"==typeof e){if(!t)return this.reporter.error("String int or enum given, but no values map");if(!t.hasOwnProperty(e))return this.reporter.error("Values map doesn't contain: "+JSON.stringify(e));e=t[e]}if("number"==typeof e||l.isBuffer(e)||(r=e.toArray(),!e.sign&&128&r[0]&&r.unshift(0),e=l.from(r)),l.isBuffer(e)){var r=e.length;0===e.length&&r++;r=l.alloc(r);return e.copy(r),0===e.length&&(r[0]=0),this._createEncoderBuffer(r)}if(e<128)return this._createEncoderBuffer(e);if(e<256)return this._createEncoderBuffer([0,e]);for(var i=1,n=e;256<=n;n>>=8)i++;for(var a=new Array(i),o=a.length-1;0<=o;o--)a[o]=255&e,e>>=8;return 128&a[0]&&a.unshift(0),this._createEncoderBuffer(l.from(a))},o.prototype._encodeBool=function(e){return this._createEncoderBuffer(e?255:0)},o.prototype._use=function(e,t){return(e="function"==typeof e?e(t):e)._getEncoder("der").tree},o.prototype._skipDefault=function(e,t,r){var i,n=this._baseState;if(null===n.default)return!1;var a=e.join();if(void 0===n.defaultBuffer&&(n.defaultBuffer=this._encodeValue(n.default,t,r).join()),a.length!==n.defaultBuffer.length)return!1;for(i=0;i=this._size)return null;var t=255&this._buf[e++];if(null===t)return null;if(128==(128&t)){if(0===(t&=127))throw a("Indefinite length not supported");if(4this._size-r)return null;if(this._offset=r,0===this.length)return t?i.alloc(0):"";r=this._buf.slice(this._offset,this._offset+this.length);return this._offset+=this.length,t?r:r.toString("utf8")},s.prototype.readOID=function(e){e=e||o.OID;var t=this.readString(e,!0);if(null===t)return null;for(var r=[],i=0,n=0;n>0),r.join(".")},s.prototype._readTag=function(e){n.ok(void 0!==e);var t=this.peek();if(null===t)return null;if(t!==e)throw a("Expected 0x"+e.toString(16)+": got 0x"+t.toString(16));t=this.readLength(this._offset+1);if(null===t)return null;if(4this._size-t)return null;this._offset=t;for(var t=this._buf[this._offset],r=0,i=0;i>0},t.exports=s},{"./errors":61,"./types":64,assert:68,"safer-buffer":422}],64:[function(e,t,r){t.exports={EOC:0,Boolean:1,Integer:2,BitString:3,OctetString:4,Null:5,OID:6,ObjectDescriptor:7,External:8,Real:9,Enumeration:10,PDV:11,Utf8String:12,RelativeOID:13,Sequence:16,Set:17,NumericString:18,PrintableString:19,T61String:20,VideotexString:21,IA5String:22,UTCTime:23,GeneralizedTime:24,GraphicString:25,VisibleString:26,GeneralString:28,UniversalString:29,CharacterString:30,BMPString:31,Constructor:32,Context:128}},{}],65:[function(e,t,r){var n=e("assert"),a=e("safer-buffer").Buffer,o=e("./types"),i=e("./errors").newInvalidAsn1Error,s={size:1024,growthFactor:8};function u(e){var r,i;r=s,i=e||{},n.ok(r),n.equal(_typeof(r),"object"),n.ok(i),n.equal(_typeof(i),"object"),Object.getOwnPropertyNames(r).forEach(function(e){var t;i[e]||(t=Object.getOwnPropertyDescriptor(r,e),Object.defineProperty(i,e,t))}),e=i,this._buf=a.alloc(e.size||1024),this._size=this._buf.length,this._offset=0,this._options=e,this._seq=[]}Object.defineProperty(u.prototype,"buffer",{get:function(){if(this._seq.length)throw i(this._seq.length+" unended sequence(s)");return this._buf.slice(0,this._offset)}}),u.prototype.writeByte=function(e){if("number"!=typeof e)throw new TypeError("argument must be a Number");this._ensure(1),this._buf[this._offset++]=e},u.prototype.writeInt=function(e,t){if("number"!=typeof e)throw new TypeError("argument must be a Number");"number"!=typeof t&&(t=o.Integer);for(var r=4;(0==(4286578688&e)||-8388608==(4286578688&e))&&1 0xffffffff");for(this._ensure(2+r),this._buf[this._offset++]=t,this._buf[this._offset++]=r;0>>24,e<<=8},u.prototype.writeNull=function(){this.writeByte(o.Null),this.writeByte(0)},u.prototype.writeEnumeration=function(e,t){if("number"!=typeof e)throw new TypeError("argument must be a Number");return"number"!=typeof t&&(t=o.Enumeration),this.writeInt(e,t)},u.prototype.writeBoolean=function(e,t){if("boolean"!=typeof e)throw new TypeError("argument must be a Boolean");"number"!=typeof t&&(t=o.Boolean),this._ensure(3),this._buf[this._offset++]=t,this._buf[this._offset++]=1,this._buf[this._offset++]=e?255:0},u.prototype.writeString=function(e,t){if("string"!=typeof e)throw new TypeError("argument must be a string (was: "+_typeof(e)+")");"number"!=typeof t&&(t=o.OctetString);var r=a.byteLength(e);this.writeByte(t),this.writeLength(r),r&&(this._ensure(r),this._buf.write(e,this._offset),this._offset+=r)},u.prototype.writeBuffer=function(e,t){if("number"!=typeof t)throw new TypeError("tag must be a number");if(!a.isBuffer(e))throw new TypeError("argument must be a buffer");this.writeByte(t),this.writeLength(e.length),this._ensure(e.length),e.copy(this._buf,this._offset,0,e.length),this._offset+=e.length},u.prototype.writeStringArray=function(e){if(!e instanceof Array)throw new TypeError("argument must be an Array[String]");var t=this;e.forEach(function(e){t.writeString(e)})},u.prototype.writeOID=function(e,t){if("string"!=typeof e)throw new TypeError("argument must be a string");if("number"!=typeof t&&(t=o.OID),!/^([0-9]+\.){3,}[0-9]+$/.test(e))throw new Error("argument is not a valid OID string");var e=e.split("."),r=[];r.push(40*parseInt(e[0],10)+parseInt(e[1],10)),e.slice(2).forEach(function(e){var t;t=r,(e=parseInt(e,10))<128?t.push(e):(e<16384?t.push(e>>>7|128):(e<2097152?t.push(e>>>14|128):(e<268435456?t.push(e>>>21|128):(t.push(255&(e>>>28|128)),t.push(255&(e>>>21|128))),t.push(255&(e>>>14|128))),t.push(255&(e>>>7|128))),t.push(127&e))});var i=this;this._ensure(2+r.length),this.writeByte(t),this.writeLength(r.length),r.forEach(function(e){i.writeByte(e)})},u.prototype.writeLength=function(e){if("number"!=typeof e)throw new TypeError("argument must be a Number");if(this._ensure(4),e<=127)this._buf[this._offset++]=e;else if(e<=255)this._buf[this._offset++]=129,this._buf[this._offset++]=e;else if(e<=65535)this._buf[this._offset++]=130,this._buf[this._offset++]=e>>8,this._buf[this._offset++]=e;else{if(!(e<=16777215))throw i("Length too long (> 4 bytes)");this._buf[this._offset++]=131,this._buf[this._offset++]=e>>16,this._buf[this._offset++]=e>>8,this._buf[this._offset++]=e}},u.prototype.startSequence=function(e){"number"!=typeof e&&(e=o.Sequence|o.Constructor),this.writeByte(e),this._seq.push(this._offset),this._ensure(3),this._offset+=3},u.prototype.endSequence=function(){var e=this._seq.pop(),t=e+3,r=this._offset-t;if(r<=127)this._shift(t,r,-2),this._buf[e]=r;else if(r<=255)this._shift(t,r,-1),this._buf[e]=129,this._buf[e+1]=r;else if(r<=65535)this._buf[e]=130,this._buf[e+1]=r>>8,this._buf[e+2]=r;else{if(!(r<=16777215))throw i("Sequence too long");this._shift(t,r,1),this._buf[e]=131,this._buf[e+1]=r>>16,this._buf[e+2]=r>>8,this._buf[e+3]=r}},u.prototype._shift=function(e,t,r){n.ok(void 0!==e),n.ok(void 0!==t),n.ok(r),this._buf.copy(this._buf,e+r,e,e+t),this._offset+=r},u.prototype._ensure=function(e){var t;n.ok(e),this._size-this._offset>>0,a=new Uint8Array(n);e[t];){var o=h[e.charCodeAt(t)];if(255===o)return;for(var s=0,u=n-1;(0!==o||s>>0,a[u]=o%256>>>0,o=o/256>>>0;if(0!==o)throw new Error("Non-zero carry");i=s,t++}if(" "!==e[t]){for(var c=n-i;c!==n&&0===a[c];)c++;var f=y.allocUnsafe(r+(n-c));f.fill(0,0,r);for(var p=r;c!==n;)f[p++]=a[c++];return f}}}return{encode:function(e){if((Array.isArray(e)||e instanceof Uint8Array)&&(e=y.from(e)),!y.isBuffer(e))throw new TypeError("Expected Buffer");if(0===e.length)return"";for(var t=0,r=0,i=0,n=e.length;i!==n&&0===e[i];)i++,t++;for(var a=(n-i)*b+1>>>0,o=new Uint8Array(a);i!==n;){for(var s=e[i],u=0,c=a-1;(0!==s||u>>0,o[c]=s%d>>>0,s=s/d>>>0;if(0!==s)throw new Error("Non-zero carry");r=u,i++}for(var f=a-r;f!==a&&0===o[f];)f++;for(var p=m.repeat(t);f>16&255,a[o++]=t>>8&255,a[o++]=255&t;2===i&&(t=u[e.charCodeAt(r)]<<2|u[e.charCodeAt(r+1)]>>4,a[o++]=255&t);1===i&&(t=u[e.charCodeAt(r)]<<10|u[e.charCodeAt(r+1)]<<4|u[e.charCodeAt(r+2)]>>2,a[o++]=t>>8&255,a[o++]=255&t);return a},r.fromByteArray=function(e){for(var t,r=e.length,i=r%3,n=[],a=0,o=r-i;a>18&63]+s[e>>12&63]+s[e>>6&63]+s[63&e]}(i));return n.join("")}(e,a,o>2]+s[t<<4&63]+"==")):2==i&&(t=(e[r-2]<<8)+e[r-1],n.push(s[t>>10]+s[t>>4&63]+s[t<<2&63]+"="));return n.join("")};for(var s=[],u=[],c="undefined"!=typeof Uint8Array?Uint8Array:Array,i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,a=i.length;n>>24,r[4*i+2]=a[i]>>>16,r[4*i+1]=a[i]>>>8,r[4*i+0]=a[i]}t.exports={BLOCKS:f,HASHSIZE:32,hash:_,pbkdf:function(e,t,r,i,n,a,o){var s,u,c,f,p,l,h=new Uint8Array(64),d=new Uint8Array(64),m=new Uint8Array(32),g=new Uint8Array(32),b=new Uint8Array(i+4),y=a;if(o<1)return-1;if(0===t||0===i||0===a||a>m.byteLength*m.byteLength||1<<20>>24,b[i+1]=l>>>16,b[i+2]=l>>>8,b[i+3]=l,v(d,b,i+4),_(h,d,g),s=m.byteLength;s--;)m[s]=g[s];for(s=1;s>25;return(33554431&e)<<5^996825010&-(t>>0&1)^642813549&-(t>>1&1)^513874426&-(t>>2&1)^1027748829&-(t>>3&1)^705979059&-(t>>4&1)}function p(e){for(var t=1,r=0;r>5}for(t=f(t),r=0;r>a&o);if(i)0t)throw new TypeError("Exceeds length limit");var r=e.toLowerCase(),t=e.toUpperCase();if(e!==r&&e!==t)throw new Error("Mixed-case string "+e);if(-1===(t=(e=r).lastIndexOf("1")))throw new Error("No separator character for "+e);if(0===t)throw new Error("Missing prefix for "+e);var r=e.slice(0,t),i=e.slice(t+1);if(i.length<6)throw new Error("Data too short");for(var n=p(r),a=[],o=0;o=i.length||a.push(u)}if(1!==n)throw new Error("Invalid checksum for "+e);return{prefix:r,words:a}},encode:function(e,t,r){if(r=r||90,e.length+7+t.length>r)throw new TypeError("Exceeds length limit");for(var i=p(e=e.toLowerCase()),n=e+"1",a=0;a>5!=0)throw new Error("Non 5-bit word");i=f(i)^o,n+=s.charAt(o)}for(a=0;a<6;++a)i=f(i);for(i^=1,a=0;a<6;++a)n+=s.charAt(i>>5*(5-a)&31);return n},toWords:function(e){return a(e,8,5,!0)},fromWords:function(e){return a(e,5,8,!1)}}},{}],79:[function(i,n,e){(function(t,r){(function(){"use strict";var e=n.exports;e.version="v"+i("./package.json").version,e.versionGuard=function(e){if(void 0!==e)throw new Error("More than one instance of bitcore-lib found. Please make sure to require bitcore-lib and check that submodules do not also include their own bitcore-lib dependency.")},e.versionGuard(t._bitcore),t._bitcore=e.version,e.crypto={},e.crypto.BN=i("./lib/crypto/bn"),e.crypto.ECDSA=i("./lib/crypto/ecdsa"),e.crypto.Hash=i("./lib/crypto/hash"),e.crypto.Random=i("./lib/crypto/random"),e.crypto.Point=i("./lib/crypto/point"),e.crypto.Signature=i("./lib/crypto/signature"),e.encoding={},e.encoding.Base58=i("./lib/encoding/base58"),e.encoding.Base58Check=i("./lib/encoding/base58check"),e.encoding.BufferReader=i("./lib/encoding/bufferreader"),e.encoding.BufferWriter=i("./lib/encoding/bufferwriter"),e.encoding.Varint=i("./lib/encoding/varint"),e.util={},e.util.buffer=i("./lib/util/buffer"),e.util.js=i("./lib/util/js"),e.util.preconditions=i("./lib/util/preconditions"),e.errors=i("./lib/errors"),e.Address=i("./lib/address"),e.Block=i("./lib/block"),e.MerkleBlock=i("./lib/block/merkleblock"),e.BlockHeader=i("./lib/block/blockheader"),e.HDPrivateKey=i("./lib/hdprivatekey.js"),e.HDPublicKey=i("./lib/hdpublickey.js"),e.Message=i("./lib/message"),e.Networks=i("./lib/networks"),e.Opcode=i("./lib/opcode"),e.PrivateKey=i("./lib/privatekey"),e.PublicKey=i("./lib/publickey"),e.Script=i("./lib/script"),e.Transaction=i("./lib/transaction"),e.URI=i("./lib/uri"),e.Unit=i("./lib/unit"),e.deps={},e.deps.bnjs=i("bn.js"),e.deps.bs58=i("bs58"),e.deps.Buffer=r,e.deps.elliptic=i("elliptic"),e.deps._=i("lodash"),e.Transaction.sighash=i("./lib/transaction/sighash")}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},i("buffer").Buffer)},{"./lib/address":80,"./lib/block":83,"./lib/block/blockheader":82,"./lib/block/merkleblock":84,"./lib/crypto/bn":85,"./lib/crypto/ecdsa":86,"./lib/crypto/hash":87,"./lib/crypto/point":88,"./lib/crypto/random":89,"./lib/crypto/signature":90,"./lib/encoding/base58":91,"./lib/encoding/base58check":92,"./lib/encoding/bufferreader":94,"./lib/encoding/bufferwriter":95,"./lib/encoding/varint":96,"./lib/errors":97,"./lib/hdprivatekey.js":99,"./lib/hdpublickey.js":100,"./lib/message":101,"./lib/networks":102,"./lib/opcode":103,"./lib/privatekey":104,"./lib/publickey":105,"./lib/script":106,"./lib/transaction":109,"./lib/transaction/sighash":117,"./lib/unit":122,"./lib/uri":123,"./lib/util/buffer":124,"./lib/util/js":125,"./lib/util/preconditions":126,"./package.json":127,"bn.js":129,bs58:183,buffer:186,elliptic:213,lodash:318}],80:[function(e,t,r){(function(d){(function(){"use strict";var o=e("lodash"),n=e("./util/preconditions"),r=e("./errors"),a=e("./encoding/base58check"),s=e("./encoding/bech32"),u=e("./networks"),c=e("./crypto/hash"),f=e("./util/js"),p=e("./publickey");function l(e,t,r,i){if(!(this instanceof l))return new l(e,t,r);if(o.isArray(e)&&o.isNumber(t))return l.createMultisig(e,t,r,!1,i);if(e instanceof l)return e;if(n.checkArgument(e,"First argument is required, please include address data.","guide/address.html"),t&&!u.get(t))throw new TypeError('Second argument must be "livenet" or "testnet".');if(r&&r!==l.PayToPublicKeyHash&&r!==l.PayToScriptHash&&r!==l.PayToWitnessPublicKeyHash&&r!==l.PayToWitnessScriptHash)throw new TypeError('Third argument must be "pubkeyhash", "scripthash", "witnesspubkeyhash", or "witnessscripthash".');e=this._classifyArguments(e,t,r);return e.network=e.network||u.get(t)||u.defaultNetwork,e.type=e.type||r||l.PayToPublicKeyHash,f.defineImmutable(this,{hashBuffer:e.hashBuffer,network:e.network,type:e.type}),this}l.prototype._classifyArguments=function(e,t,r){if(!(e instanceof d||e instanceof Uint8Array)||20!==e.length&&32!==e.length){if((e instanceof d||e instanceof Uint8Array)&&21<=e.length)return l._transformBuffer(e,t,r);if(e instanceof p)return l._transformPublicKey(e,t,r);if(e instanceof h)return l._transformScript(e,t);if("string"==typeof e)return l._transformString(e,t,r);if(o.isObject(e))return l._transformObject(e);throw new TypeError("First argument is an unrecognized data format.")}return l._transformHash(e,t,r)},l.PayToPublicKeyHash="pubkeyhash",l.PayToScriptHash="scripthash",l.PayToWitnessPublicKeyHash="witnesspubkeyhash",l.PayToWitnessScriptHash="witnessscripthash",l._transformHash=function(e,t,r){var i={};if(!(e instanceof d||e instanceof Uint8Array))throw new TypeError("Address supplied is not a buffer.");if(20!==e.length&&32!==e.length)throw new TypeError("Address hashbuffers must be either 20 or 32 bytes.");return i.hashBuffer=e,i.network=u.get(t)||u.defaultNetwork,i.type=r,i},l._transformObject=function(e){return n.checkArgument(e.hash||e.hashBuffer,"Must provide a `hash` or `hashBuffer` property"),n.checkArgument(e.type,"Must provide a `type` property"),{hashBuffer:e.hash?d.from(e.hash,"hex"):e.hashBuffer,network:u.get(e.network)||u.defaultNetwork,type:e.type}},l._classifyFromVersion=function(e){var t={};if(21"},t.exports=l;var h=e("./script")}).call(this)}).call(this,e("buffer").Buffer)},{"./crypto/hash":87,"./encoding/base58check":92,"./encoding/bech32":93,"./errors":97,"./networks":102,"./publickey":105,"./script":106,"./util/js":125,"./util/preconditions":126,buffer:186,lodash:318}],81:[function(t,h,e){(function(l){(function(){"use strict";var r=t("lodash"),n=t("./blockheader"),i=t("../crypto/bn"),a=t("../util/buffer"),o=t("../encoding/bufferreader"),s=t("../encoding/bufferwriter"),u=t("../crypto/hash"),c=t("../transaction"),f=t("../util/preconditions");function p(e){return this instanceof p?(r.extend(this,p._from(e)),this):new p(e)}p.MAX_BLOCK_SIZE=1e6,p._from=function(e){var t={};if(a.isBuffer(e))t=p._fromBufferReader(o(e));else{if(!r.isObject(e))throw new TypeError("Unrecognized argument for Block");t=p._fromObject(e)}return t},p._fromObject=function(e){var t=[];return e.transactions.forEach(function(e){e instanceof c?t.push(e):t.push(c().fromObject(e))}),{header:n.fromObject(e.header),transactions:t}},p.fromObject=function(e){e=p._fromObject(e);return new p(e)},p._fromBufferReader=function(e){var t={};f.checkState(!e.finished(),"No block data received"),t.header=n.fromBufferReader(e);var r=e.readVarintNum();t.transactions=[];for(var i=0;i"},p.Values={START_OF_BLOCK:8,NULL_HASH:l.from("0000000000000000000000000000000000000000000000000000000000000000","hex")},h.exports=p}).call(this)}).call(this,t("buffer").Buffer)},{"../crypto/bn":85,"../crypto/hash":87,"../encoding/bufferreader":94,"../encoding/bufferwriter":95,"../transaction":109,"../util/buffer":124,"../util/preconditions":126,"./blockheader":82,buffer:186,lodash:318}],82:[function(f,p,e){(function(c){(function(){"use strict";function r(e){return this instanceof r?(e=r._from(e),this.version=e.version,this.prevHash=e.prevHash,this.merkleRoot=e.merkleRoot,this.time=e.time,this.timestamp=e.time,this.bits=e.bits,this.nonce=e.nonce,e.hash&&u.checkState(this.hash===e.hash,"Argument object hash property does not match block hash."),this):new r(e)}var i=f("lodash"),n=f("../crypto/bn"),a=f("../util/buffer"),o=f("../encoding/bufferreader"),t=f("../encoding/bufferwriter"),s=f("../crypto/hash"),u=(f("../util/js"),f("../util/preconditions"));r._from=function(e){var t={};if(a.isBuffer(e))t=r._fromBufferReader(o(e));else{if(!i.isObject(e))throw new TypeError("Unrecognized argument for BlockHeader");t=r._fromObject(e)}return t},r._fromObject=function(e){u.checkArgument(e,"data is required");var t=e.prevHash,r=e.merkleRoot;return i.isString(e.prevHash)&&(t=a.reverse(c.from(e.prevHash,"hex"))),i.isString(e.merkleRoot)&&(r=a.reverse(c.from(e.merkleRoot,"hex"))),{hash:e.hash,version:e.version,prevHash:t,merkleRoot:r,time:e.time,timestamp:e.time,bits:e.bits,nonce:e.nonce}},r.fromObject=function(e){e=r._fromObject(e);return new r(e)},r.fromRawBlock=function(e){a.isBuffer(e)||(e=c.from(e,"binary"));e=o(e);e.pos=r.Constants.START_OF_HEADER;e=r._fromBufferReader(e);return new r(e)},r.fromBuffer=function(e){e=r._fromBufferReader(o(e));return new r(e)},r.fromString=function(e){e=c.from(e,"hex");return r.fromBuffer(e)},r._fromBufferReader=function(e){var t={};return t.version=e.readInt32LE(),t.prevHash=e.read(32),t.merkleRoot=e.read(32),t.time=e.readUInt32LE(),t.bits=e.readUInt32LE(),t.nonce=e.readUInt32LE(),t},r.fromBufferReader=function(e){e=r._fromBufferReader(e);return new r(e)},r.prototype.toObject=r.prototype.toJSON=function(){return{hash:this.hash,version:this.version,prevHash:a.reverse(this.prevHash).toString("hex"),merkleRoot:a.reverse(this.merkleRoot).toString("hex"),time:this.time,bits:this.bits,nonce:this.nonce}},r.prototype.toBuffer=function(){return this.toBufferWriter().concat()},r.prototype.toString=function(){return this.toBuffer().toString("hex")},r.prototype.toBufferWriter=function(e){return(e=e||new t).writeInt32LE(this.version),e.write(this.prevHash),e.write(this.merkleRoot),e.writeUInt32LE(this.time),e.writeUInt32LE(this.bits),e.writeUInt32LE(this.nonce),e},r.prototype.getTargetDifficulty=function(e){e=e||this.bits;for(var t=new n(16777215&e),r=8*((e>>>24)-3);0e+r.Constants.MAX_TIME_OFFSET)},r.prototype.validProofOfWork=function(){var e=new n(this.id,"hex"),t=this.getTargetDifficulty();return!(0"},r.Constants={START_OF_HEADER:8,MAX_TIME_OFFSET:7200,LARGEST_HASH:new n("10000000000000000000000000000000000000000000000000000000000000000","hex")},p.exports=r}).call(this)}).call(this,f("buffer").Buffer)},{"../crypto/bn":85,"../crypto/hash":87,"../encoding/bufferreader":94,"../encoding/bufferwriter":95,"../util/buffer":124,"../util/js":125,"../util/preconditions":126,buffer:186,lodash:318}],83:[function(e,t,r){t.exports=e("./block"),t.exports.BlockHeader=e("./blockheader"),t.exports.MerkleBlock=e("./merkleblock")},{"./block":81,"./blockheader":82,"./merkleblock":84}],84:[function(e,t,r){(function(l){(function(){"use strict";var i=e("lodash"),a=e("./blockheader"),n=e("../util/buffer"),o=e("../encoding/bufferreader"),r=e("../encoding/bufferwriter"),s=e("../crypto/hash"),u=(e("../util/js"),e("../transaction")),c=e("../errors"),f=e("../util/preconditions");function p(e){if(!(this instanceof p))return new p(e);var t={};if(n.isBuffer(e))t=p._fromBufferReader(o(e));else{if(!i.isObject(e))throw new TypeError("Unrecognized argument for MerkleBlock");var r=e.header instanceof a?e.header:a.fromObject(e.header),t={header:r,numTransactions:e.numTransactions,hashes:e.hashes,flags:e.flags}}return i.extend(this,t),this._flagBitsUsed=0,this._hashesUsed=0,this}p.fromBuffer=function(e){return p.fromBufferReader(o(e))},p.fromBufferReader=function(e){return new p(p._fromBufferReader(e))},p.prototype.toBuffer=function(){return this.toBufferWriter().concat()},p.prototype.toBufferWriter=function(e){(e=e||new r).write(this.header.toBuffer()),e.writeUInt32LE(this.numTransactions),e.writeVarintNum(this.hashes.length);for(var t=0;tthis.numTransactions)return!1;if(8*this.flags.lengththis.numTransactions)throw new c.MerkleBlock.InvalidMerkleTree;if(8*this.flags.length8*this.flags.length)return null;var n=this.flags[r.flagBitsUsed>>3]>>>(7&r.flagBitsUsed++)&1;if(0!==e&&n){var a=this._traverseMerkleTree(e-1,2*t,r),o=a;return 2*t+1=this.hashes.length)return null;o=this.hashes[r.hashesUsed++];return 0===e&&n&&r.txs.push(o),l.from(o,"hex")},p.prototype._calcTreeWidth=function(e){return this.numTransactions+(1<>e},p.prototype._calcTreeHeight=function(){for(var e=0;1e.size?i=a.trim(i,r):r>1,o=f.getN(),e=f.getG(),a=a?r.add(o):r,a=f.fromX(n,a);if(!a.mul(o).isInfinity())throw new Error("nR is not a valid curve point");t=t.neg().umod(o),o=r.invm(o),o=a.mul(i).add(e.mul(t)).mul(o);return s.fromPoint(o,this.sig.compressed)},u.prototype.sigError=function(){if(!l.isBuffer(this.hashbuf)||32!==this.hashbuf.length)return"hashbuf must be a 32 byte buffer";var e=this.sig.r,t=this.sig.s;if(!(e.gt(c.Zero)&&e.lt(f.getN())&&t.gt(c.Zero)&&t.lt(f.getN())))return"r and s not in range";var r=c.fromBuffer(this.hashbuf,this.endian?{endian:this.endian}:void 0),i=f.getN(),t=t.invm(i),r=t.mul(r).umod(i),t=t.mul(e).umod(i),t=f.getG().mulAdd(r,this.pubkey.point,t);return t.isInfinity()?"p is infinity":0!==t.getX().umod(i).cmp(e)&&"Invalid signature"},u.toLowS=function(e){return e=e.gt(c.fromBuffer(m.from("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0","hex")))?f.getN().sub(e):e},u.prototype._findSignature=function(e,t){for(var r,i,n,a=f.getN(),o=f.getG(),s=0;(!this.k||0n?r=e(r):r>>=8);return r},e.exports=t}).call(this)}).call(this,i("_process"),i("buffer").Buffer)},{_process:354,buffer:186,crypto:198}],90:[function(e,r,t){(function(o){(function(){"use strict";function a(e,t){if(!(this instanceof a))return new a(e,t);e instanceof h?this.set({r:e,s:t}):e&&this.set(e)}var h=e("./bn"),d=e("lodash"),m=e("../util/preconditions"),g=e("../util/buffer"),t=e("../util/js");a.prototype.set=function(e){return this.r=e.r||this.r||void 0,this.s=e.s||this.s||void 0,this.i=(void 0!==e.i?e:this).i,this.compressed=(void 0!==e.compressed?e:this).compressed,this.nhashtype=e.nhashtype||this.nhashtype||void 0,this},a.fromCompact=function(e){m.checkArgument(g.isBuffer(e),"Argument is expected to be a Buffer");var t=new a,r=!0,i=e.slice(0,1)[0]-27-4;i<0&&(r=!1,i+=4);var n=e.slice(1,33),e=e.slice(33,65);return m.checkArgument(0===i||1===i||2===i||3===i,new Error("i must be 0, 1, 2, or 3")),m.checkArgument(32===n.length,new Error("r must be 32 bytes")),m.checkArgument(32===e.length,new Error("s must be 32 bytes")),t.compressed=r,t.i=i,t.r=h.fromBuffer(n),t.s=h.fromBuffer(e),t},a.fromDER=a.fromBuffer=function(e,t){e=a.parseDER(e,t),t=new a;return t.r=e.r,t.s=e.s,t},a.fromTxFormat=function(e){var t=e.readUInt8(e.length-1),e=e.slice(0,e.length-1),e=new a.fromDER(e,!1);return e.nhashtype=t,e},a.fromString=function(e){e=o.from(e,"hex");return a.fromDER(e)},a.parseDER=function(e,t){m.checkArgument(g.isBuffer(e),new Error("DER formatted signature should be a buffer")),d.isUndefined(t)&&(t=!0);var r=e[0];m.checkArgument(48===r,new Error("Header byte should be 0x30"));var i=e[1],n=e.slice(2).length;m.checkArgument(!t||i===n,new Error("Length byte should length of what follows")),i=i=e.length)return!1;var r=e[5+t];if(t+r+7!==e.length)return!1;var i=e.slice(4);if(2!==e[2])return!1;if(0===t)return!1;if(128&i[0])return!1;if(1=this.buf.length},t.prototype.read=function(e){i.checkArgument(!r.isUndefined(e),"Must specify a length");var t=this.buf.slice(this.pos,this.pos+e);return this.pos=this.pos+e,t},t.prototype.readAll=function(){var e=this.buf.slice(this.pos,this.buf.length);return this.pos=this.buf.length,e},t.prototype.readUInt8=function(){var e=this.buf.readUInt8(this.pos);return this.pos=this.pos+1,e},t.prototype.readUInt16BE=function(){var e=this.buf.readUInt16BE(this.pos);return this.pos=this.pos+2,e},t.prototype.readUInt16LE=function(){var e=this.buf.readUInt16LE(this.pos);return this.pos=this.pos+2,e},t.prototype.readUInt32BE=function(){var e=this.buf.readUInt32BE(this.pos);return this.pos=this.pos+4,e},t.prototype.readUInt32LE=function(){var e=this.buf.readUInt32LE(this.pos);return this.pos=this.pos+4,e},t.prototype.readInt32LE=function(){var e=this.buf.readInt32LE(this.pos);return this.pos=this.pos+4,e},t.prototype.readUInt64BEBN=function(){var e=this.buf.slice(this.pos,this.pos+8),e=a.fromBuffer(e);return this.pos=this.pos+8,e},t.prototype.readUInt64LEBN=function(){var e,t=this.buf.readUInt32LE(this.pos),t=4294967296*this.buf.readUInt32LE(this.pos+4)+t;return e=t<=9007199254740991?new a(t):(e=Array.prototype.slice.call(this.buf,this.pos,this.pos+8),new a(e,10,"le")),this.pos=this.pos+8,e},t.prototype.readVarintNum=function(){var e=this.readUInt8();switch(e){case 253:return this.readUInt16LE();case 254:return this.readUInt32LE();case 255:var t=this.readUInt64LEBN().toNumber();if(t<=Math.pow(2,53))return t;throw new Error("number too large to retain precision - use readVarintBN");default:return e}},t.prototype.readVarLengthBuffer=function(){var e=this.readVarintNum(),t=this.read(e);return i.checkState(t.length===e,"Invalid length while reading varlength buffer. Expected to read: "+e+" and read "+t.length),t},t.prototype.readVarintBuf=function(){switch(this.buf.readUInt8(this.pos)){case 253:return this.read(3);case 254:return this.read(5);case 255:return this.read(9);default:return this.read(1)}},t.prototype.readVarintBN=function(){var e=this.readUInt8();switch(e){case 253:return new a(this.readUInt16LE());case 254:return new a(this.readUInt32LE());case 255:return this.readUInt64LEBN();default:return new a(e)}},t.prototype.reverse=function(){for(var e=o.alloc(this.buf.length),t=0;t=y.Hardened||t,e"},y.prototype.toObject=y.prototype.toJSON=function(){return{network:p.get(g.integerFromBuffer(this._buffers.version),"xprivkey").name,depth:g.integerFromSingleByteBuffer(this._buffers.depth),fingerPrint:g.integerFromBuffer(this.fingerPrint),parentFingerPrint:g.integerFromBuffer(this._buffers.parentFingerPrint),childIndex:g.integerFromBuffer(this._buffers.childIndex),chainCode:g.bufferToHex(this._buffers.chainCode),privateKey:this.privateKey.toBuffer().toString("hex"),checksum:g.integerFromBuffer(this._buffers.checksum),xprivkey:this.xprivkey}},y.fromBuffer=function(e){return new y(e.toString())},y.prototype.toBuffer=function(){return g.copy(this._buffers.xprivkey)},y.DefaultDepth=0,y.DefaultFingerprint=0,y.DefaultChildIndex=0,y.Hardened=2147483648,y.MaxIndex=2*y.Hardened,y.RootElementAlias=["m","M","m'","M'"],y.VersionSize=4,y.DepthSize=1,y.ParentFingerPrintSize=4,y.ChildIndexSize=4,y.ChainCodeSize=32,y.PrivateKeySize=32,y.CheckSumSize=4,y.DataLength=78,y.SerializedByteSize=82,y.VersionStart=0,y.VersionEnd=y.VersionStart+y.VersionSize,y.DepthStart=y.VersionEnd,y.DepthEnd=y.DepthStart+y.DepthSize,y.ParentFingerPrintStart=y.DepthEnd,y.ParentFingerPrintEnd=y.ParentFingerPrintStart+y.ParentFingerPrintSize,y.ChildIndexStart=y.ParentFingerPrintEnd,y.ChildIndexEnd=y.ChildIndexStart+y.ChildIndexSize,y.ChainCodeStart=y.ChildIndexEnd,y.ChainCodeEnd=y.ChainCodeStart+y.ChainCodeSize,y.PrivateKeyStart=y.ChainCodeEnd+1,y.PrivateKeyEnd=y.PrivateKeyStart+y.PrivateKeySize,y.ChecksumStart=y.PrivateKeyEnd,y.ChecksumEnd=y.ChecksumStart+y.CheckSumSize,o(y.ChecksumEnd===y.SerializedByteSize),e.exports=y}).call(this)}).call(this,a("buffer").Buffer)},{"./crypto/bn":85,"./crypto/hash":87,"./crypto/point":88,"./crypto/random":89,"./encoding/base58":91,"./encoding/base58check":92,"./errors":97,"./hdpublickey":100,"./networks":102,"./privatekey":104,"./util/buffer":124,"./util/js":125,"./util/preconditions":126,assert:68,buffer:186,lodash:318}],100:[function(y,v,e){(function(b){(function(){"use strict";var i=y("lodash"),t=y("./util/preconditions"),n=y("./crypto/bn"),a=y("./encoding/base58"),o=y("./encoding/base58check"),s=y("./crypto/hash"),r=y("./hdprivatekey"),u=y("./networks"),c=y("./crypto/point"),f=y("./publickey"),e=y("./errors"),p=e,l=e.HDPublicKey,h=y("assert"),d=y("./util/js"),m=y("./util/buffer");function g(e){if(e instanceof g)return e;if(!(this instanceof g))return new g(e);if(e){if(i.isString(e)||m.isBuffer(e)){var t=g.getSerializedError(e);if(t){if(m.isBuffer(e)&&!g.getSerializedError(e.toString()))return this._buildFromSerialized(e.toString());if(t instanceof l.ArgumentIsPrivateExtended)return new r(e).hdPublicKey;throw t}return this._buildFromSerialized(e)}if(i.isObject(e))return e instanceof r?this._buildFromPrivate(e):this._buildFromObject(e);throw new l.UnrecognizedArgument(e)}throw new l.MustSupplyArgument}g.isValidPath=function(e){if(i.isString(e)){var t=r._getDerivationIndexes(e);return null!==t&&i.every(t,g.isValidPath)}return!!i.isNumber(e)&&(0<=e&&e=g.Hardened||e)throw new l.InvalidIndexCantDeriveHardened;if(t<0)throw new l.InvalidPath(t);var r,e=m.integerAsBuffer(t),e=m.concat([this.publicKey.toBuffer(),e]),e=s.sha512hmac(e,this._buffers.chainCode),i=n.fromBuffer(e.slice(0,32),{size:32}),e=e.slice(32,64);try{r=f.fromPoint(c.getG().mul(i).add(this.publicKey.point))}catch(e){return this._deriveWithNumber(t+1)}return new g({network:this.network,depth:this.depth+1,parentFingerPrint:this.fingerPrint,childIndex:t,chainCode:e,publicKey:r})},g.prototype._deriveFromString=function(e){if(i.includes(e,"'"))throw new l.InvalidIndexCantDeriveHardened;if(!g.isValidPath(e))throw new l.InvalidPath(e);return r._getDerivationIndexes(e).reduce(function(e,t){return e._deriveWithNumber(t)},this)},g.isValidSerialized=function(e,t){return i.isNull(g.getSerializedError(e,t))},g.getSerializedError=function(t,e){if(!i.isString(t)&&!m.isBuffer(t))return new l.UnrecognizedArgument("expected buffer or string");if(!a.validCharacters(t))return new p.InvalidB58Char("(unknown)",t);try{t=o.decode(t)}catch(e){return new p.InvalidB58Checksum(t)}if(t.length!==g.DataSize)return new l.InvalidLength(t);if(!i.isUndefined(e)){var r=g._validateNetwork(t,e);if(r)return r}r=m.integerFromBuffer(t.slice(0,4));return r===u.livenet.xprivkey||r===u.testnet.xprivkey?new l.ArgumentIsPrivateExtended:null},g._validateNetwork=function(e,t){var r=u.get(t);if(!r)return new p.InvalidNetworkArgument(t);e=e.slice(g.VersionStart,g.VersionEnd);return m.integerFromBuffer(e)!==r.xpubkey?new p.InvalidNetwork(e):null},g.prototype._buildFromPrivate=function(e){var t=i.clone(e._buffers),e=c.getG().mul(n.fromBuffer(t.privateKey));return t.publicKey=c.pointToCompressed(e),t.version=m.integerAsBuffer(u.get(m.integerFromBuffer(t.version)).xpubkey),t.privateKey=void 0,t.checksum=void 0,t.xprivkey=void 0,this._buildFromBuffers(t)},g.prototype._buildFromObject=function(e){e={version:e.network?m.integerAsBuffer(u.get(e.network).xpubkey):e.version,depth:i.isNumber(e.depth)?m.integerAsSingleByteBuffer(e.depth):e.depth,parentFingerPrint:i.isNumber(e.parentFingerPrint)?m.integerAsBuffer(e.parentFingerPrint):e.parentFingerPrint,childIndex:i.isNumber(e.childIndex)?m.integerAsBuffer(e.childIndex):e.childIndex,chainCode:i.isString(e.chainCode)?b.from(e.chainCode,"hex"):e.chainCode,publicKey:i.isString(e.publicKey)?b.from(e.publicKey,"hex"):m.isBuffer(e.publicKey)?e.publicKey:e.publicKey.toBuffer(),checksum:i.isNumber(e.checksum)?m.integerAsBuffer(e.checksum):e.checksum};return this._buildFromBuffers(e)},g.prototype._buildFromSerialized=function(e){var t=o.decode(e),e={version:t.slice(g.VersionStart,g.VersionEnd),depth:t.slice(g.DepthStart,g.DepthEnd),parentFingerPrint:t.slice(g.ParentFingerPrintStart,g.ParentFingerPrintEnd),childIndex:t.slice(g.ChildIndexStart,g.ChildIndexEnd),chainCode:t.slice(g.ChainCodeStart,g.ChainCodeEnd),publicKey:t.slice(g.PublicKeyStart,g.PublicKeyEnd),checksum:t.slice(g.ChecksumStart,g.ChecksumEnd),xpubkey:e};return this._buildFromBuffers(e)},g.prototype._buildFromBuffers=function(e){g._validateBufferArguments(e),d.defineImmutable(this,{_buffers:e});var t=[e.version,e.depth,e.parentFingerPrint,e.childIndex,e.chainCode,e.publicKey],r=m.concat(t),i=o.checksum(r);if(e.checksum&&e.checksum.length){if(e.checksum.toString("hex")!==i.toString("hex"))throw new p.InvalidB58Checksum(r,i)}else e.checksum=i;var n=u.get(m.integerFromBuffer(e.version)),r=o.encode(m.concat(t));e.xpubkey=b.from(r);i=new f(e.publicKey,{network:n}),t=g.ParentFingerPrintSize,t=s.sha256ripemd160(i.toBuffer()).slice(0,t);return d.defineImmutable(this,{xpubkey:r,network:n,depth:m.integerFromSingleByteBuffer(e.depth),publicKey:i,fingerPrint:t}),this},g._validateBufferArguments=function(i){function e(e,t){var r=i[e];h(m.isBuffer(r),e+" argument is not a buffer, it's "+_typeof(r)),h(r.length===t,e+" has not the expected size: found "+r.length+", expected "+t)}e("version",g.VersionSize),e("depth",g.DepthSize),e("parentFingerPrint",g.ParentFingerPrintSize),e("childIndex",g.ChildIndexSize),e("chainCode",g.ChainCodeSize),e("publicKey",g.PublicKeySize),i.checksum&&i.checksum.length&&e("checksum",g.CheckSumSize)},g.fromString=function(e){return t.checkArgument(i.isString(e),"No valid string was provided"),new g(e)},g.fromObject=function(e){return t.checkArgument(i.isObject(e),"No valid argument was provided"),new g(e)},g.prototype.toString=function(){return this.xpubkey},g.prototype.inspect=function(){return""},g.prototype.toObject=g.prototype.toJSON=function(){return{network:u.get(m.integerFromBuffer(this._buffers.version)).name,depth:m.integerFromSingleByteBuffer(this._buffers.depth),fingerPrint:m.integerFromBuffer(this.fingerPrint),parentFingerPrint:m.integerFromBuffer(this._buffers.parentFingerPrint),childIndex:m.integerFromBuffer(this._buffers.childIndex),chainCode:m.bufferToHex(this._buffers.chainCode),publicKey:this.publicKey.toString(),checksum:m.integerFromBuffer(this._buffers.checksum),xpubkey:this.xpubkey}},g.fromBuffer=function(e){return new g(e)},g.prototype.toBuffer=function(){return m.copy(this._buffers.xpubkey)},g.Hardened=2147483648,g.RootElementAlias=["m","M"],g.VersionSize=4,g.DepthSize=1,g.ParentFingerPrintSize=4,g.ChildIndexSize=4,g.ChainCodeSize=32,g.PublicKeySize=33,g.CheckSumSize=4,g.DataSize=78,g.SerializedByteSize=82,g.VersionStart=0,g.VersionEnd=g.VersionStart+g.VersionSize,g.DepthStart=g.VersionEnd,g.DepthEnd=g.DepthStart+g.DepthSize,g.ParentFingerPrintStart=g.DepthEnd,g.ParentFingerPrintEnd=g.ParentFingerPrintStart+g.ParentFingerPrintSize,g.ChildIndexStart=g.ParentFingerPrintEnd,g.ChildIndexEnd=g.ChildIndexStart+g.ChildIndexSize,g.ChainCodeStart=g.ChildIndexEnd,g.ChainCodeEnd=g.ChainCodeStart+g.ChainCodeSize,g.PublicKeyStart=g.ChainCodeEnd,g.PublicKeyEnd=g.PublicKeyStart+g.PublicKeySize,g.ChecksumStart=g.PublicKeyEnd,g.ChecksumEnd=g.ChecksumStart+g.CheckSumSize,h(g.PublicKeyEnd===g.DataSize),h(g.ChecksumEnd===g.SerializedByteSize),v.exports=g}).call(this)}).call(this,y("buffer").Buffer)},{"./crypto/bn":85,"./crypto/hash":87,"./crypto/point":88,"./encoding/base58":91,"./encoding/base58check":92,"./errors":97,"./hdprivatekey":99,"./networks":102,"./publickey":105,"./util/buffer":124,"./util/js":125,"./util/preconditions":126,assert:68,buffer:186,lodash:318}],101:[function(e,r,t){(function(h){(function(){"use strict";var n=e("lodash"),i=e("./privatekey"),a=e("./publickey"),o=e("./address"),s=e("./encoding/bufferwriter"),u=e("./crypto/ecdsa"),c=e("./crypto/signature"),f=e("./crypto/hash").sha256sha256,t=e("./util/js"),p=e("./util/preconditions");function l(e){return this instanceof l?(p.checkArgument(n.isString(e),"First argument should be a string"),this.message=e,this):new l(e)}l.MAGIC_BYTES=h.from("Bitcoin Signed Message:\n"),l.prototype.magicHash=function(){var e=s.varintBufNum(l.MAGIC_BYTES.length),t=h.from(this.message),r=s.varintBufNum(t.length),t=h.concat([e,l.MAGIC_BYTES,r,t]);return f(t)},l.prototype._sign=function(e){p.checkArgument(e instanceof i,"First argument should be an instance of PrivateKey");var t=this.magicHash(),r=new u;return r.hashbuf=t,r.privkey=e,r.pubkey=e.toPublicKey(),r.signRandomK(),r.calci(),r.sig},l.prototype.sign=function(e){return this._sign(e).toCompact().toString("base64")},l.prototype._verify=function(e,t){p.checkArgument(e instanceof a,"First argument should be an instance of PublicKey"),p.checkArgument(t instanceof c,"Second argument should be an instance of Signature");var r=this.magicHash(),e=u.verify(r,t,e);return e||(this.error="The signature was invalid"),e},l.prototype.verify=function(e,t){p.checkArgument(e),p.checkArgument(t&&n.isString(t)),n.isString(e)&&(e=o.fromString(e));var r=c.fromCompact(h.from(t,"base64")),i=new u;i.hashbuf=this.magicHash(),i.sig=r;t=i.toPublicKey(),i=o.fromPublicKey(t,e.network);return e.toString()!==i.toString()?!(this.error="The signature did not match the message digest"):this._verify(t,r)},l.prototype.recoverPublicKey=function(e,t){p.checkArgument(e),p.checkArgument(t&&n.isString(t)),n.isString(e)&&(e=o.fromString(e));var r=c.fromCompact(h.from(t,"base64")),t=new u;t.hashbuf=this.magicHash(),t.sig=r;r=t.toPublicKey(),t=o.fromPublicKey(r,e.network);return e.toString()!==t.toString()&&(this.error="The signature did not match the message digest"),r.toString()},l.fromString=function(e){return new l(e)},l.fromJSON=function(e){return new l((e=t.isValidJSON(e)?JSON.parse(e):e).message)},l.prototype.toObject=function(){return{message:this.message}},l.prototype.toJSON=function(){return JSON.stringify(this.toObject())},l.prototype.toString=function(){return this.message},l.prototype.inspect=function(){return""},r.exports=l;e("./script")}).call(this)}).call(this,e("buffer").Buffer)},{"./address":80,"./crypto/ecdsa":86,"./crypto/hash":87,"./crypto/signature":90,"./encoding/bufferwriter":95,"./privatekey":104,"./publickey":105,"./script":106,"./util/js":125,"./util/preconditions":126,buffer:186,lodash:318}],102:[function(e,t,r){"use strict";var n=e("lodash"),i=e("./util/buffer"),a=e("./util/js"),o=[],s={};function u(){}function c(t,e){if(~o.indexOf(t))return t;if(!e)return s[t]&&1<=s[t].length?s[t][0]:s[t];n.isArray(e)||(e=[e]);function r(e){return o[i][e]===t}for(var i in o)if(n.some(e,r))return o[i]}function f(e){var t=new u;return a.defineImmutable(t,{name:e.name,alias:e.alias,pubkeyhash:e.pubkeyhash,privatekey:e.privatekey,scripthash:e.scripthash,bech32prefix:e.bech32prefix,xpubkey:e.xpubkey,xprivkey:e.xprivkey}),e.networkMagic&&a.defineImmutable(t,{networkMagic:i.integerAsBuffer(e.networkMagic)}),e.port&&a.defineImmutable(t,{port:e.port}),e.dnsSeeds&&a.defineImmutable(t,{dnsSeeds:e.dnsSeeds}),n.each(t,function(e){n.isUndefined(e)||n.isObject(e)||(s[e]||(s[e]=[]),s[e].push(t))}),o.push(t),t}u.prototype.toString=function(){return this.name},f({name:"livenet",alias:"mainnet",pubkeyhash:0,privatekey:128,scripthash:5,bech32prefix:"bc",xpubkey:76067358,xprivkey:76066276,networkMagic:4190024921,port:8333,dnsSeeds:["seed.bitcoin.sipa.be","dnsseed.bluematt.me","dnsseed.bitcoin.dashjr.org","seed.bitcoinstats.com","seed.bitnodes.io","bitseed.xf2.org"]});var p=c("livenet");f({name:"testnet",alias:"test",pubkeyhash:111,privatekey:239,scripthash:196,bech32prefix:"tb",xpubkey:70617039,xprivkey:70615956,networkMagic:185665799,port:18333,dnsSeeds:["testnet-seed.bitcoin.petertodd.org","testnet-seed.bluematt.me","testnet-seed.alexykot.me","testnet-seed.bitcoin.schildbach.de"]});var l=c("testnet");f({name:"regtest",alias:"dev",pubkeyhash:111,privatekey:239,scripthash:196,bech32prefix:"bcrt",xpubkey:70617039,xprivkey:70615956,networkMagic:4206867930,port:18444,dnsSeeds:[]});e=c("regtest");t.exports={add:f,remove:function(e){for(var t,r=0;r=a.map.OP_1&&e<=a.map.OP_16},a.prototype.inspect=function(){return""},u.exports=a}).call(this)}).call(this,s("buffer").Buffer)},{"./util/buffer":124,"./util/js":125,"./util/preconditions":126,buffer:186,lodash:318}],104:[function(l,h,e){(function(p){(function(){"use strict";var i=l("lodash"),n=l("./address"),r=l("./encoding/base58check"),a=l("./crypto/bn"),o=l("./util/js"),s=l("./networks"),u=l("./crypto/point"),e=l("./publickey"),c=l("./crypto/random"),t=l("./util/preconditions");function f(e,t){if(!(this instanceof f))return new f(e,t);if(e instanceof f)return e;t=this._classifyArguments(e,t);if(!t.bn||0===t.bn.cmp(new a(0)))throw new TypeError("Number can not be equal to zero, undefined, null or false");if(!t.bn.lt(u.getN()))throw new TypeError("Number must be less than N");if(void 0===t.network)throw new TypeError('Must specify the network ("livenet" or "testnet")');return o.defineImmutable(this,{bn:t.bn,compressed:t.compressed,network:t.network}),Object.defineProperty(this,"publicKey",{configurable:!1,enumerable:!0,get:this.toPublicKey.bind(this)}),this}f.prototype._classifyArguments=function(e,t){var r={compressed:!0,network:t?s.get(t):s.defaultNetwork};if(i.isUndefined(e)||i.isNull(e))r.bn=f._getRandomBN();else if(e instanceof a)r.bn=e;else if(e instanceof p||e instanceof Uint8Array)r=f._transformBuffer(e,t);else if(e.bn&&e.network)r=f._transformObject(e);else if(!t&&s.get(e))r.bn=f._getRandomBN(),r.network=s.get(e);else{if("string"!=typeof e)throw new TypeError("First argument is an unrecognized data type.");o.isHexa(e)?r.bn=new a(p.from(e,"hex")):r=f._transformWIF(e,t)}return r},f._getRandomBN=function(){do{var e,t=c.getRandomBuffer(32),t=(e=a.fromBuffer(t)).lt(u.getN())}while(!t);return e},f._transformBuffer=function(e,t){var r={};if(32===e.length)return f._transformBNBuffer(e,t);if(r.network=s.get(e[0],"privatekey"),!r.network)throw new Error("Invalid network");if(t&&r.network!==s.get(t))throw new TypeError("Private key network mismatch");if(34===e.length&&1===e[33])r.compressed=!0;else{if(33!==e.length)throw new Error("Length of buffer must be 33 (uncompressed) or 34 (compressed)");r.compressed=!1}return r.bn=a.fromBuffer(e.slice(1,33)),r},f._transformBNBuffer=function(e,t){var r={};return r.network=s.get(t)||s.defaultNetwork,r.bn=a.fromBuffer(e),r.compressed=!1,r},f._transformWIF=function(e,t){return f._transformBuffer(r.decode(e),t)},f.fromBuffer=function(e,t){return new f(e,t)},f._transformObject=function(e){return{bn:new a(e.bn,"hex"),network:s.get(e.network),compressed:e.compressed}},f.fromString=f.fromWIF=function(e){return t.checkArgument(i.isString(e),"First argument is expected to be a string."),new f(e)},f.fromObject=function(e){return t.checkArgument(i.isObject(e),"First argument is expected to be an object."),new f(e)},f.fromRandom=function(e){var t=f._getRandomBN();return new f(t,e)},f.getValidationError=function(e,t){var r;try{new f(e,t)}catch(e){r=e}return r},f.isValid=function(e,t){return!!e&&!f.getValidationError(e,t)},f.prototype.toString=function(){return this.toBuffer().toString("hex")},f.prototype.toWIF=function(){var e=this.network,e=this.compressed?p.concat([p.from([e.privatekey]),this.bn.toBuffer({size:32}),p.from([1])]):p.concat([p.from([e.privatekey]),this.bn.toBuffer({size:32})]);return r.encode(e)},f.prototype.toBigNumber=function(){return this.bn},f.prototype.toBuffer=function(){return this.bn.toBuffer({size:32})},f.prototype.toBufferNoPadding=function(){return this.bn.toBuffer()},f.prototype.toPublicKey=function(){return this._pubkey||(this._pubkey=e.fromPrivateKey(this)),this._pubkey},f.prototype.toAddress=function(e,t){var r=this.toPublicKey();return n.fromPublicKey(r,e||this.network,t)},f.prototype.toObject=f.prototype.toJSON=function(){return{bn:this.bn.toString("hex"),compressed:this.compressed,network:this.network.toString()}},f.prototype.inspect=function(){var e=this.compressed?"":", uncompressed";return""},h.exports=f}).call(this)}).call(this,l("buffer").Buffer)},{"./address":80,"./crypto/bn":85,"./crypto/point":88,"./crypto/random":89,"./encoding/base58check":92,"./networks":102,"./publickey":105,"./util/js":125,"./util/preconditions":126,buffer:186,lodash:318}],105:[function(f,t,e){(function(n){(function(){"use strict";var a=f("./crypto/bn"),o=f("./crypto/point"),e=f("./crypto/hash"),r=f("./util/js"),i=f("./networks"),s=f("lodash"),u=f("./util/preconditions");function c(e,t){if(!(this instanceof c))return new c(e,t);if(u.checkArgument(e,"First argument is required, please include public key data."),e instanceof c)return e;t=t||{};t=this._classifyArgs(e,t);return t.point.validate(),r.defineImmutable(this,{point:t.point,compressed:t.compressed,network:t.network||i.defaultNetwork}),this}c.prototype._classifyArgs=function(e,t){var r={compressed:s.isUndefined(t.compressed)||t.compressed};if(e instanceof o)r.point=e;else if(e.x&&e.y)r=c._transformObject(e);else if("string"==typeof e)r=c._transformDER(n.from(e,"hex"));else if(c._isBuffer(e))r=c._transformDER(e);else{if(!c._isPrivateKey(e))throw new TypeError("First argument is an unrecognized data format.");r=c._transformPrivateKey(e)}return r.network||(r.network=s.isUndefined(t.network)?void 0:i.get(t.network)),r},c._isPrivateKey=function(e){return e instanceof f("./privatekey")},c._isBuffer=function(e){return e instanceof n||e instanceof Uint8Array},c._transformPrivateKey=function(e){u.checkArgument(c._isPrivateKey(e),"Must be an instance of PrivateKey");var t={};return t.point=o.getG().mul(e.bn),t.compressed=e.compressed,t.network=e.network,t},c._transformDER=function(e,t){u.checkArgument(c._isBuffer(e),"Must be a hex buffer of DER encoded public key");var r,i,n={};if(t=!!s.isUndefined(t)||t,4!==e[0]&&(t||6!==e[0]&&7!==e[0]))if(3===e[0])i=e.slice(1),r=new a(i),(n=c._transformX(!0,r)).compressed=!0;else{if(2!==e[0])throw new TypeError("Invalid DER format public key");i=e.slice(1),r=new a(i),(n=c._transformX(!1,r)).compressed=!0}else{if(i=e.slice(1,33),t=e.slice(33,65),32!==i.length||32!==t.length||65!==e.length)throw new TypeError("Length of x and y must be 32 bytes");r=new a(i),t=new a(t),n.point=new o(r,t),n.compressed=!1}return n},c._transformX=function(e,t){u.checkArgument("boolean"==typeof e,"Must specify whether y is odd or not (true or false)");var r={};return r.point=o.fromX(e,t),r},c._transformObject=function(e){var t=new a(e.x,"hex"),r=new a(e.y,"hex");return new c(new o(t,r),{compressed:e.compressed})},c.fromPrivateKey=function(e){u.checkArgument(c._isPrivateKey(e),"Must be an instance of PrivateKey");e=c._transformPrivateKey(e);return new c(e.point,{compressed:e.compressed,network:e.network})},c.fromDER=c.fromBuffer=function(e,t){u.checkArgument(c._isBuffer(e),"Must be a hex buffer of DER encoded public key");t=c._transformDER(e,t);return new c(t.point,{compressed:t.compressed})},c.fromPoint=function(e,t){return u.checkArgument(e instanceof o,"First argument must be an instance of Point."),new c(e,{compressed:t})},c.fromString=function(e,t){t=n.from(e,t||"hex"),t=c._transformDER(t);return new c(t.point,{compressed:t.compressed})},c.fromX=function(e,t){t=c._transformX(e,t);return new c(t.point,{compressed:t.compressed})},c.getValidationError=function(e){var t;try{new c(e)}catch(e){t=e}return t},c.isValid=function(e){return!c.getValidationError(e)},c.prototype.toObject=c.prototype.toJSON=function(){return{x:this.point.getX().toString("hex",2),y:this.point.getY().toString("hex",2),compressed:this.compressed}},c.prototype.toBuffer=c.prototype.toDER=function(){var e=this.point.getX(),t=this.point.getY(),e=e.toBuffer({size:32}),t=t.toBuffer({size:32});if(this.compressed){var r=t[t.length-1]%2?n.from([3]):n.from([2]);return n.concat([r,e])}return r=n.from([4]),n.concat([r,e,t])},c.prototype._getID=function(){return e.sha256ripemd160(this.toBuffer())},c.prototype.toAddress=function(e,t){return f("./address").fromPublicKey(this,e||this.network,t)},c.prototype.toString=function(){return this.toDER().toString("hex")},c.prototype.inspect=function(){return""},t.exports=c}).call(this)}).call(this,f("buffer").Buffer)},{"./address":80,"./crypto/bn":85,"./crypto/hash":87,"./crypto/point":88,"./networks":102,"./privatekey":104,"./util/js":125,"./util/preconditions":126,buffer:186,lodash:318}],106:[function(e,t,r){t.exports=e("./script"),t.exports.Interpreter=e("./interpreter")},{"./interpreter":107,"./script":108}],107:[function(p,t,e){(function(e){(function(){"use strict";function R(e){if(!(this instanceof R))return new R(e);e?(this.initialize(),this.set(e)):this.initialize()}var B=p("lodash"),F=p("./script"),M=p("../opcode"),z=p("../crypto/bn"),N=p("../crypto/hash"),D=p("../crypto/signature"),L=p("../publickey");R.prototype.verifyWitnessProgram=function(e,t,r,i,n){var a=new F,o=[];if(0!==e)return!(n&R.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)||!(this.errstr="SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM");if(32===t.length){if(0===r.length)return!(this.errstr="SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY");e=r[r.length-1],a=new F(e);if(N.sha256(e).toString("hex")!==t.toString("hex"))return!(this.errstr="SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH");o=r.slice(0,-1)}else{if(20!==t.length)return!(this.errstr="SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH");if(2!==r.length)return!(this.errstr="SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH");a.add(M.OP_DUP),a.add(M.OP_HASH160),a.add(t),a.add(M.OP_EQUALVERIFY),a.add(M.OP_CHECKSIG),o=r}if(this.initialize(),this.set({script:a,stack:o,sigversion:1,satoshis:i,flags:n}),!this.evaluate())return!1;if(1!==this.stack.length)return!(this.errstr="SCRIPT_ERR_EVAL_FALSE");n=this.stack[this.stack.length-1];return!!R.castToBool(n)||!(this.errstr="SCRIPT_ERR_EVAL_FALSE_IN_STACK")},R.prototype.verify=function(e,t,r,i,n,a,o){var s,u=p("../transaction");if(B.isUndefined(r)&&(r=new u),B.isUndefined(i)&&(i=0),B.isUndefined(n)&&(n=0),B.isUndefined(a)&&(a=null),B.isUndefined(o)&&(o=0),this.set({script:e,tx:r,nin:i,sigversion:0,satoshis:0,flags:n}),0!=(n&R.SCRIPT_VERIFY_SIGPUSHONLY)&&!e.isPushOnly())return!(this.errstr="SCRIPT_ERR_SIG_PUSHONLY");if(!this.evaluate())return!1;n&R.SCRIPT_VERIFY_P2SH&&(s=this.stack.slice());var c=this.stack;if(this.initialize(),this.set({script:t,stack:c,tx:r,nin:i,flags:n}),!this.evaluate())return!1;if(0===this.stack.length)return!(this.errstr="SCRIPT_ERR_EVAL_FALSE_NO_RESULT");var f=this.stack[this.stack.length-1];if(!R.castToBool(f))return!(this.errstr="SCRIPT_ERR_EVAL_FALSE_IN_STACK");u=!1;if(n&R.SCRIPT_VERIFY_WITNESS){f={};if(t.isWitnessProgram(f)){if(u=!0,0!==e.toBuffer().length)return!1;if(!this.verifyWitnessProgram(f.version,f.program,a,o,this.flags))return!1}}if(n&R.SCRIPT_VERIFY_P2SH&&t.isScriptHashOut()){if(!e.isPushOnly())return!(this.errstr="SCRIPT_ERR_SIG_PUSHONLY");if(0===s.length)throw new Error("internal error - stack copy empty");t=s[s.length-1],t=F.fromBuffer(t);if(s.pop(),this.initialize(),this.set({script:t,stack:s,tx:r,nin:i,flags:n}),!this.evaluate())return!1;if(0===s.length)return!(this.errstr="SCRIPT_ERR_EVAL_FALSE_NO_P2SH_STACK");if(!R.castToBool(s[s.length-1]))return!(this.errstr="SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK");if(n&R.SCRIPT_VERIFY_WITNESS){i={};if(t.isWitnessProgram(i)){u=!0;n=new F;if(n.add(t.toBuffer()),e.toHex()!==n.toHex())return!(this.errstr="SCRIPT_ERR_WITNESS_MALLEATED_P2SH");if(!this.verifyWitnessProgram(i.version,i.program,a,o,this.flags))return!1;c[0]}}}if(0!=(this.flags&R.SCRIPT_VERIFY_CLEANSTACK)){if(0==(this.flags&R.SCRIPT_VERIFY_P2SH))throw"flags & SCRIPT_VERIFY_P2SH";if(1!=s.length)return!(this.errstr="SCRIPT_ERR_CLEANSTACK")}return!(this.flags&R.SCRIPT_VERIFY_WITNESS&&!u&&0=R.LOCKTIME_THRESHOLD&&e.gte(R.LOCKTIME_THRESHOLD_BN))&&(!e.gt(new z(this.tx.nLockTime))&&!!this.tx.inputs[this.nin].isFinal())},R.prototype.checkSequence=function(e){var t=this.tx.inputs[this.nin].sequenceNumber;if(this.tx.version<2)return!1;if(t&SEQUENCE_LOCKTIME_DISABLE_FLAG)return!1;var r=R.SEQUENCE_LOCKTIME_TYPE_FLAG|R.SEQUENCE_LOCKTIME_MASK,t=new z(t&r),e=e.and(r),r=new z(R.SEQUENCE_LOCKTIME_TYPE_FLAG);return!!(t.lt(r)&&e.lt(r)||t.gte(r)&&e.gte(r))&&!e.gt(t)},R.prototype.step=function(){var e,t,r,i,n,a,o,s,u,c,f,p,l,h,d=0!=(this.flags&R.SCRIPT_VERIFY_MINIMALDATA),m=-1===this.vfExec.indexOf(!1),g=this.script.chunks[this.pc];this.pc++;var b=g.opcodenum;if(B.isUndefined(b))return!(this.errstr="SCRIPT_ERR_UNDEFINED_OPCODE");if(g.buf&&g.buf.length>R.MAX_SCRIPT_ELEMENT_SIZE)return!(this.errstr="SCRIPT_ERR_PUSH_SIZE");if(b>M.OP_16&&201<++this.nOpCount)return!(this.errstr="SCRIPT_ERR_OP_COUNT");if(b===M.OP_CAT||b===M.OP_SUBSTR||b===M.OP_LEFT||b===M.OP_RIGHT||b===M.OP_INVERT||b===M.OP_AND||b===M.OP_OR||b===M.OP_XOR||b===M.OP_2MUL||b===M.OP_2DIV||b===M.OP_MUL||b===M.OP_DIV||b===M.OP_MOD||b===M.OP_LSHIFT||b===M.OP_RSHIFT)return!(this.errstr="SCRIPT_ERR_DISABLED_OPCODE");if(m&&0<=b&&b<=M.OP_PUSHDATA4){if(d&&!this.script.checkMinimalPush(this.pc-1))return!(this.errstr="SCRIPT_ERR_MINIMALDATA");if(g.buf){if(g.len!==g.buf.length)throw new Error("Length of push value not equal to length of data");this.stack.push(g.buf)}else this.stack.push(R.false)}else if(m||M.OP_IF<=b&&b<=M.OP_ENDIF)switch(b){case M.OP_1NEGATE:case M.OP_1:case M.OP_2:case M.OP_3:case M.OP_4:case M.OP_5:case M.OP_6:case M.OP_7:case M.OP_8:case M.OP_9:case M.OP_10:case M.OP_11:case M.OP_12:case M.OP_13:case M.OP_14:case M.OP_15:case M.OP_16:_=b-(M.OP_1-1),x=new z(_).toScriptNumBuffer(),this.stack.push(x);break;case M.OP_NOP:break;case M.OP_NOP2:case M.OP_CHECKLOCKTIMEVERIFY:if(!(this.flags&R.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)){if(this.flags&R.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)return!(this.errstr="SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS");break}if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");var y=z.fromScriptNumBuffer(this.stack[this.stack.length-1],d,5);if(y.lt(new z(0)))return!(this.errstr="SCRIPT_ERR_NEGATIVE_LOCKTIME");if(!this.checkLockTime(y))return!(this.errstr="SCRIPT_ERR_UNSATISFIED_LOCKTIME");break;case M.OP_NOP3:case M.OP_CHECKSEQUENCEVERIFY:if(!(this.flags&R.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)){if(this.flags&R.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)return!(this.errstr="SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS");break}if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");var v=z.fromScriptNumBuffer(this.stack[this.stack.length-1],d,5);if(v.lt(new z(0)))return!(this.errstr="SCRIPT_ERR_NEGATIVE_LOCKTIME");if(0!=(v&R.SEQUENCE_LOCKTIME_DISABLE_FLAG))break;if(!this.checkSequence(v))return!(this.errstr="SCRIPT_ERR_UNSATISFIED_LOCKTIME");break;case M.OP_NOP1:case M.OP_NOP4:case M.OP_NOP5:case M.OP_NOP6:case M.OP_NOP7:case M.OP_NOP8:case M.OP_NOP9:case M.OP_NOP10:if(this.flags&R.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)return!(this.errstr="SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS");break;case M.OP_IF:case M.OP_NOTIF:if(k=!1,m){if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_UNBALANCED_CONDITIONAL");if(x=this.stack[this.stack.length-1],this.flags&R.SCRIPT_VERIFY_MINIMALIF){if(1<(x=this.stack[this.stack.length-1]).length)return!(this.errstr="SCRIPT_ERR_MINIMALIF");if(1==x.length&&1!=x[0])return!(this.errstr="SCRIPT_ERR_MINIMALIF")}k=R.castToBool(x),b===M.OP_NOTIF&&(k=!k),this.stack.pop()}this.vfExec.push(k);break;case M.OP_ELSE:if(0===this.vfExec.length)return!(this.errstr="SCRIPT_ERR_UNBALANCED_CONDITIONAL");this.vfExec[this.vfExec.length-1]=!this.vfExec[this.vfExec.length-1];break;case M.OP_ENDIF:if(0===this.vfExec.length)return!(this.errstr="SCRIPT_ERR_UNBALANCED_CONDITIONAL");this.vfExec.pop();break;case M.OP_VERIFY:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");if(x=this.stack[this.stack.length-1],!(k=R.castToBool(x)))return!(this.errstr="SCRIPT_ERR_VERIFY");this.stack.pop();break;case M.OP_RETURN:return!(this.errstr="SCRIPT_ERR_OP_RETURN");case M.OP_TOALTSTACK:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.altstack.push(this.stack.pop());break;case M.OP_FROMALTSTACK:if(this.altstack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_ALTSTACK_OPERATION");this.stack.push(this.altstack.pop());break;case M.OP_2DROP:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.stack.pop(),this.stack.pop();break;case M.OP_2DUP:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");e=this.stack[this.stack.length-2],t=this.stack[this.stack.length-1],this.stack.push(e),this.stack.push(t);break;case M.OP_3DUP:if(this.stack.length<3)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");e=this.stack[this.stack.length-3],t=this.stack[this.stack.length-2];v=this.stack[this.stack.length-1];this.stack.push(e),this.stack.push(t),this.stack.push(v);break;case M.OP_2OVER:if(this.stack.length<4)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");e=this.stack[this.stack.length-4],t=this.stack[this.stack.length-3],this.stack.push(e),this.stack.push(t);break;case M.OP_2ROT:if(this.stack.length<6)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");r=this.stack.splice(this.stack.length-6,2),this.stack.push(r[0]),this.stack.push(r[1]);break;case M.OP_2SWAP:if(this.stack.length<4)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");r=this.stack.splice(this.stack.length-4,2),this.stack.push(r[0]),this.stack.push(r[1]);break;case M.OP_IFDUP:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");x=this.stack[this.stack.length-1],(k=R.castToBool(x))&&this.stack.push(x);break;case M.OP_DEPTH:x=new z(this.stack.length).toScriptNumBuffer(),this.stack.push(x);break;case M.OP_DROP:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.stack.pop();break;case M.OP_DUP:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.stack.push(this.stack[this.stack.length-1]);break;case M.OP_NIP:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.stack.splice(this.stack.length-2,1);break;case M.OP_OVER:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.stack.push(this.stack[this.stack.length-2]);break;case M.OP_PICK:case M.OP_ROLL:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");if(x=this.stack[this.stack.length-1],_=(a=z.fromScriptNumBuffer(x,d)).toNumber(),this.stack.pop(),_<0||_>=this.stack.length)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");x=this.stack[this.stack.length-_-1],b===M.OP_ROLL&&this.stack.splice(this.stack.length-_-1,1),this.stack.push(x);break;case M.OP_ROT:if(this.stack.length<3)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");i=this.stack[this.stack.length-3],n=this.stack[this.stack.length-2];var _=this.stack[this.stack.length-1];this.stack[this.stack.length-3]=n,this.stack[this.stack.length-2]=_,this.stack[this.stack.length-1]=i;break;case M.OP_SWAP:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");i=this.stack[this.stack.length-2],n=this.stack[this.stack.length-1],this.stack[this.stack.length-2]=n,this.stack[this.stack.length-1]=i;break;case M.OP_TUCK:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");this.stack.splice(this.stack.length-2,0,this.stack[this.stack.length-1]);break;case M.OP_SIZE:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");a=new z(this.stack[this.stack.length-1].length),this.stack.push(a.toScriptNumBuffer());break;case M.OP_EQUAL:case M.OP_EQUALVERIFY:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");e=this.stack[this.stack.length-2],t=this.stack[this.stack.length-1];var w=e.toString("hex")===t.toString("hex");if(this.stack.pop(),this.stack.pop(),this.stack.push(w?R.true:R.false),b===M.OP_EQUALVERIFY){if(!w)return!(this.errstr="SCRIPT_ERR_EQUALVERIFY");this.stack.pop()}break;case M.OP_1ADD:case M.OP_1SUB:case M.OP_NEGATE:case M.OP_ABS:case M.OP_NOT:case M.OP_0NOTEQUAL:if(this.stack.length<1)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");switch(x=this.stack[this.stack.length-1],a=z.fromScriptNumBuffer(x,d),b){case M.OP_1ADD:a=a.add(z.One);break;case M.OP_1SUB:a=a.sub(z.One);break;case M.OP_NEGATE:a=a.neg();break;case M.OP_ABS:a.cmp(z.Zero)<0&&(a=a.neg());break;case M.OP_NOT:a=new z(+(0===a.cmp(z.Zero)));break;case M.OP_0NOTEQUAL:a=new z(+(0!==a.cmp(z.Zero)))}this.stack.pop(),this.stack.push(a.toScriptNumBuffer());break;case M.OP_ADD:case M.OP_SUB:case M.OP_BOOLAND:case M.OP_BOOLOR:case M.OP_NUMEQUAL:case M.OP_NUMEQUALVERIFY:case M.OP_NUMNOTEQUAL:case M.OP_LESSTHAN:case M.OP_GREATERTHAN:case M.OP_LESSTHANOREQUAL:case M.OP_GREATERTHANOREQUAL:case M.OP_MIN:case M.OP_MAX:if(this.stack.length<2)return!(this.errstr="SCRIPT_ERR_INVALID_STACK_OPERATION");switch(o=z.fromScriptNumBuffer(this.stack[this.stack.length-2],d),s=z.fromScriptNumBuffer(this.stack[this.stack.length-1],d),a=new z(0),b){case M.OP_ADD:a=o.add(s);break;case M.OP_SUB:a=o.sub(s);break;case M.OP_BOOLAND:a=new z(+(0!==o.cmp(z.Zero)&&0!==s.cmp(z.Zero)));break;case M.OP_BOOLOR:a=new z(+(0!==o.cmp(z.Zero)||0!==s.cmp(z.Zero)));break;case M.OP_NUMEQUAL:case M.OP_NUMEQUALVERIFY:a=new z(+(0===o.cmp(s)));break;case M.OP_NUMNOTEQUAL:a=new z(+(0!==o.cmp(s)));break;case M.OP_LESSTHAN:a=new z(+(o.cmp(s)<0));break;case M.OP_GREATERTHAN:a=new z(+(0"},s.prototype.isPublicKeyHashOut=function(){return!(5!==this.chunks.length||this.chunks[0].opcodenum!==u.OP_DUP||this.chunks[1].opcodenum!==u.OP_HASH160||!this.chunks[2].buf||20!==this.chunks[2].buf.length||this.chunks[3].opcodenum!==u.OP_EQUALVERIFY||this.chunks[4].opcodenum!==u.OP_CHECKSIG)},s.prototype.isPublicKeyHashIn=function(){if(2===this.chunks.length){var e=this.chunks[0].buf,t=this.chunks[1].buf;if(e&&e.length&&48===e[0]&&t&&t.length){e=t[0];if((4===e||6===e||7===e)&&65===t.length)return!0;if((3===e||2===e)&&33===t.length)return!0}}return!1},s.prototype.getPublicKey=function(){return p.checkState(this.isPublicKeyOut(),"Can't retrieve PublicKey from a non-PK output"),this.chunks[0].buf},s.prototype.getPublicKeyHash=function(){if(this.isPublicKeyHashOut())return this.chunks[2].buf;if(this.isWitnessPublicKeyHashOut())return this.chunks[1].buf;throw new Error("Can't retrieve PublicKeyHash from a non-PKH output")},s.prototype.isPublicKeyOut=function(){if(2===this.chunks.length&&this.chunks[0].buf&&this.chunks[0].buf.length&&this.chunks[1].opcodenum===u.OP_CHECKSIG){var e=this.chunks[0].buf,t=e[0],r=!1;if(r=(4===t||6===t||7===t)&&65===e.length||(3===t||2===t)&&33===e.length?!0:r)return c.isValid(e)}return!1},s.prototype.isPublicKeyIn=function(){if(1===this.chunks.length){var e=this.chunks[0].buf;if(e&&e.length&&48===e[0])return!0}return!1},s.prototype.isScriptHashOut=function(){var e=this.toBuffer();return 23===e.length&&e[0]===u.OP_HASH160&&20===e[1]&&e[e.length-1]===u.OP_EQUAL},s.prototype.isWitnessScriptHashOut=function(){var e=this.toBuffer();return 34===e.length&&0===e[0]&&32===e[1]},s.prototype.isWitnessPublicKeyHashOut=function(){var e=this.toBuffer();return 22===e.length&&0===e[0]&&20===e[1]},s.prototype.isWitnessProgram=function(e){e=e||{};var t=this.toBuffer();return!(t.length<4||42=u.OP_1&&t[0]<=u.OP_16)&&(t.length===t[1]+2&&(e.version=t[0],e.program=t.slice(2,t.length),!0)))},s.prototype.isScriptHashIn=function(){if(this.chunks.length<=1)return!1;var e,t=this.chunks[this.chunks.length-1].buf;if(!t)return!1;try{e=s.fromBuffer(t)}catch(e){if(e instanceof h.Script.InvalidBuffer)return!1;throw e}return e.classify()!==s.types.UNKNOWN},s.prototype.isMultisigOut=function(){return 3=u.OP_1&&e<=u.OP_16)return e-(u.OP_1-1);throw new Error("Invalid opcode: "+JSON.stringify(e))},s.prototype.getSignatureOperationsCount=function(t){t=!!l.isUndefined(t)||t;var r=this,i=0,n=u.OP_INVALIDOPCODE;return l.each(r.chunks,function(e){e=e.opcodenum;e==u.OP_CHECKSIG||e==u.OP_CHECKSIGVERIFY?i++:e!=u.OP_CHECKMULTISIG&&e!=u.OP_CHECKMULTISIGVERIFY||(t&&n>=u.OP_1&&n<=u.OP_16?i+=r._decodeOP_N(n):i+=20),n=e}),i},t.exports=s}).call(this)}).call(this,e("buffer").Buffer)},{"../address":80,"../crypto/hash":87,"../crypto/signature":90,"../encoding/bufferreader":94,"../encoding/bufferwriter":95,"../errors":97,"../networks":102,"../opcode":103,"../publickey":105,"../util/buffer":124,"../util/js":125,"../util/preconditions":126,buffer:186,lodash:318}],109:[function(e,t,r){t.exports=e("./transaction"),t.exports.Input=e("./input"),t.exports.Output=e("./output"),t.exports.UnspentOutput=e("./unspentoutput"),t.exports.Signature=e("./signature"),t.exports.Sighash=e("./sighash"),t.exports.SighashWitness=e("./sighashwitness")},{"./input":110,"./output":116,"./sighash":117,"./sighashwitness":118,"./signature":119,"./transaction":120,"./unspentoutput":121}],110:[function(e,t,r){t.exports=e("./input"),t.exports.PublicKey=e("./publickey"),t.exports.PublicKeyHash=e("./publickeyhash"),t.exports.MultiSig=e("./multisig.js"),t.exports.MultiSigScriptHash=e("./multisigscripthash.js")},{"./input":111,"./multisig.js":112,"./multisigscripthash.js":113,"./publickey":114,"./publickeyhash":115}],111:[function(m,g,e){(function(d){(function(){"use strict";var r=m("lodash"),t=m("../../util/preconditions"),i=m("../../errors"),n=m("../../encoding/bufferwriter"),a=(m("buffer"),m("../../util/buffer")),o=m("../../util/js"),s=m("../../script"),u=m("../sighash"),c=m("../output"),e=4294967295,f=Math.pow(2,31),p=Math.pow(2,22),l=Math.pow(2,16)-1;function h(e){return this instanceof h?e?this._fromObject(e):void 0:new h(e)}h.MAXINT=e,h.DEFAULT_SEQNUMBER=4294967295,h.DEFAULT_LOCKTIME_SEQNUMBER=4294967294,h.DEFAULT_RBF_SEQNUMBER=4294967293,h.SEQUENCE_LOCKTIME_TYPE_FLAG=p,Object.defineProperty(h.prototype,"script",{configurable:!1,enumerable:!0,get:function(){return this.isNull()?null:(this._script||(this._script=new s(this._scriptBuffer),this._script._isInput=!0),this._script)}}),h.fromObject=function(e){return t.checkArgument(r.isObject(e)),(new h)._fromObject(e)},h.prototype._fromObject=function(e){var t=r.isString(e.prevTxId)&&o.isHexa(e.prevTxId)?d.from(e.prevTxId,"hex"):e.prevTxId;if(this.witnesses=[],this.output=e.output?e.output instanceof c?e.output:new c(e.output):void 0,this.prevTxId=t||e.txidbuf,this.outputIndex=r.isUndefined(e.outputIndex)?e.txoutnum:e.outputIndex,this.sequenceNumber=r.isUndefined(e.sequenceNumber)?r.isUndefined(e.seqnum)?4294967295:e.seqnum:e.sequenceNumber,r.isUndefined(e.script)&&r.isUndefined(e.scriptBuffer))throw new i.Transaction.Input.MissingScript;return this.setScript(e.scriptBuffer||e.script),this},h.prototype.toObject=h.prototype.toJSON=function(){var e={prevTxId:this.prevTxId.toString("hex"),outputIndex:this.outputIndex,sequenceNumber:this.sequenceNumber,script:this._scriptBuffer.toString("hex")};return this.script&&(e.scriptString=this.script.toString()),this.output&&(e.output=this.output.toObject()),e},h.fromBufferReader=function(e){var t=new h;return t.prevTxId=e.readReverse(32),t.outputIndex=e.readUInt32LE(),t._scriptBuffer=e.readVarLengthBuffer(),t.sequenceNumber=e.readUInt32LE(),t},h.prototype.toBufferWriter=function(e){(e=e||new n).writeReverse(this.prevTxId),e.writeUInt32LE(this.outputIndex);var t=this._scriptBuffer;return e.writeVarintNum(t.length),e.write(t),e.writeUInt32LE(this.sequenceNumber),e},h.prototype.setScript=function(e){if(this._script=null,e instanceof s)this._script=e,this._script._isInput=!0,this._scriptBuffer=e.toBuffer();else if(o.isHexa(e))this._scriptBuffer=d.from(e,"hex");else if(r.isString(e))this._script=new s(e),this._script._isInput=!0,this._scriptBuffer=this._script.toBuffer();else{if(!a.isBuffer(e))throw new TypeError("Invalid argument type: script");this._scriptBuffer=d.from(e)}return this},h.prototype.getSignatures=function(){throw new i.AbstractMethodInvoked("Trying to sign unsupported output type (only P2PKH and P2SH multisig inputs are supported) for input: "+JSON.stringify(this))},h.prototype.getSatoshisBuffer=function(){return t.checkState(this.output instanceof c),t.checkState(this.output._satoshisBN),(new n).writeUInt64LEBN(this.output._satoshisBN).toBuffer()},h.prototype.isFullySigned=function(){throw new i.AbstractMethodInvoked("Input#isFullySigned")},h.prototype.isFinal=function(){return this.sequenceNumber!==h.MAXINT},h.prototype.addSignature=function(){throw new i.AbstractMethodInvoked("Input#addSignature")},h.prototype.clearSignatures=function(){throw new i.AbstractMethodInvoked("Input#clearSignatures")},h.prototype.hasWitnesses=function(){return!!(this.witnesses&&0"},c.fromBufferReader=function(e){var t={};t.satoshis=e.readUInt64LEBN();var r=e.readVarintNum();return t.script=0!==r?e.read(r):f.from([]),new c(t)},c.prototype.toBufferWriter=function(e){(e=e||new a).writeUInt64LEBN(this._satoshisBN);var t=this._scriptBuffer;return e.writeVarintNum(t.length),e.write(t),e},p.exports=c}).call(this)}).call(this,e("buffer").Buffer)},{"../crypto/bn":85,"../encoding/bufferwriter":95,"../errors":97,"../script":106,"../util/buffer":124,"../util/js":125,"../util/preconditions":126,buffer:186,lodash:318}],117:[function(y,e,t){(function(b){(function(){"use strict";y("buffer");function o(e,t,r,i){var n,a=y("./transaction"),o=y("./input"),s=a.shallowCopy(e);for((i=new c(i)).removeCodeseparators(),n=0;n=s.outputs.length)return b.from("0000000000000000000000000000000000000000000000000000000000000001","hex");for(s.outputs.length=r+1,n=0;n"},S.prototype.toBuffer=function(e){var t=new c;return this.toBufferWriter(t,e).toBuffer()},S.prototype.hasWitnesses=function(){for(var e=0;e=S.NLOCKTIME_BLOCKHEIGHT_LIMIT)throw new a.Transaction.BlockHeightTooHigh;if(e<0)throw new a.Transaction.NLockTimeOutOfRange;for(var t=0;t=this.inputs.length)throw new a.Transaction.InvalidIndex(e,this.inputs.length);e=this.inputs[e];this.inputs=u.without(this.inputs,e),this._inputAmount=void 0,this._updateChangeOutput()},S.prototype.sign=function(e,t,r){l.checkState(this.hasAllUtxoInfo(),"Not all utxo information is available to sign the transaction.");var i=this;return u.isArray(e)?u.each(e,function(e){i.sign(e,t,r)}):u.each(this.getSignatures(e,t,r),function(e){i.applySignature(e,r)}),this},S.prototype.getSignatures=function(r,i,n){r=new k(r),i=i||f.SIGHASH_ALL;var a=this,o=[],s=e.sha256ripemd160(r.publicKey.toBuffer());return u.each(this.inputs,function(e,t){u.each(e.getSignatures(a,r,t,i,s,n),function(e){o.push(e)})}),o},S.prototype.applySignature=function(e,t){return this.inputs[e.inputIndex].addSignature(this,e,t),this},S.prototype.isFullySigned=function(){return u.each(this.inputs,function(e){if(e.isFullySigned===m.prototype.isFullySigned)throw new a.Transaction.UnableToVerifySignature("Unrecognized script kind, or not enough information to execute script.This usually happens when creating a transaction from a serialized transaction")}),u.every(u.map(this.inputs,function(e){return e.isFullySigned()}))},S.prototype.isValidSignature=function(e,t){if(this.inputs[e.inputIndex].isValidSignature===m.prototype.isValidSignature)throw new a.Transaction.UnableToVerifySignature("Unrecognized script kind, or not enough information to execute script.This usually happens when creating a transaction from a serialized transaction");return this.inputs[e.inputIndex].isValidSignature(this,e,t)},S.prototype.verifySignature=function(e,t,r,i,n,a,o){if(1!==(n=u.isUndefined(n)?0:n))return p.verify(this,e,t,r,i,o);n=i.toBuffer(),i=new c;return i.writeVarintNum(n.length),i.write(n),a=a?(l.checkState(s.isNaturalNumber(a)),(new c).writeUInt64LEBN(new x(a)).toBuffer()):this.inputs[r].getSatoshisBuffer(),h.verify(this,e,t,r,i.toBuffer(),a,o)},S.prototype.verify=function(){if(0===this.inputs.length)return"transaction txins empty";if(0===this.outputs.length)return"transaction txouts empty";for(var e=new x(0),t=0;t=m.MAXINT-1&&(t.sequenceNumber=m.DEFAULT_RBF_SEQNUMBER)}return this},S.prototype.setVersion=function(e){return l.checkArgument(s.isNaturalNumber(e)&&e<=2,"Wrong version number"),this.version=e,this},I.exports=S}).call(this)}).call(this,P("buffer").Buffer)},{"../address":80,"../crypto/bn":85,"../crypto/hash":87,"../crypto/signature":90,"../encoding/bufferreader":94,"../encoding/bufferwriter":95,"../errors":97,"../privatekey":104,"../script":106,"../util/buffer":124,"../util/js":125,"../util/preconditions":126,"./input":110,"./output":116,"./sighash":117,"./sighashwitness":118,"./unspentoutput":121,buffer:186,"buffer-compare":184,lodash:318}],121:[function(e,t,r){"use strict";var a=e("lodash"),o=e("../util/preconditions"),s=e("../util/js"),u=e("../script"),c=e("../address"),f=e("../unit");function p(e){if(!(this instanceof p))return new p(e);o.checkArgument(a.isObject(e),"Must provide an object from where to extract data");var t=e.address?new c(e.address):void 0,r=e.txid||e.txId;if(!r||!s.isHexaString(r)||64"},p.prototype.toString=function(){return this.txId+":"+this.outputIndex},p.fromObject=function(e){return new p(e)},p.prototype.toObject=p.prototype.toJSON=function(){return{address:this.address?this.address.toString():void 0,txid:this.txId,vout:this.outputIndex,scriptPubKey:this.script.toBuffer().toString("hex"),amount:f.fromSatoshis(this.satoshis).toBTC()}},t.exports=p},{"../address":80,"../script":106,"../unit":122,"../util/js":125,"../util/preconditions":126,lodash:318}],122:[function(e,t,r){"use strict";var i=e("lodash"),n=e("./errors"),a=e("./util/preconditions"),o={BTC:[1e8,8],mBTC:[1e5,5],uBTC:[100,2],bits:[100,2],satoshis:[1,0]};function s(e,t){if(!(this instanceof s))return new s(e,t);if(i.isNumber(t)){if(t<=0)throw new n.Unit.InvalidRate(t);e/=t,t=s.BTC}this._value=this._from(e,t);var r=this;Object.keys(o).forEach(function(e){Object.defineProperty(r,e,{get:function(){return r.to(e)},enumerable:!0})})}Object.keys(o).forEach(function(e){s[e]=e}),s.fromObject=function(e){return a.checkArgument(i.isObject(e),"Argument is expected to be an object"),new s(e.amount,e.code)},s.fromBTC=function(e){return new s(e,s.BTC)},s.fromMillis=s.fromMilis=function(e){return new s(e,s.mBTC)},s.fromMicros=s.fromBits=function(e){return new s(e,s.bits)},s.fromSatoshis=function(e){return new s(e,s.satoshis)},s.fromFiat=function(e,t){return new s(e,t)},s.prototype._from=function(e,t){if(!o[t])throw new n.Unit.UnknownCode(t);return parseInt((e*o[t][0]).toFixed())},s.prototype.to=function(e){if(i.isNumber(e)){if(e<=0)throw new n.Unit.InvalidRate(e);return parseFloat((this.BTC*e).toFixed(2))}if(!o[e])throw new n.Unit.UnknownCode(e);var t=this._value/o[e][0];return parseFloat(t.toFixed(o[e][1]))},s.prototype.toBTC=function(){return this.to(s.BTC)},s.prototype.toMillis=s.prototype.toMilis=function(){return this.to(s.mBTC)},s.prototype.toMicros=s.prototype.toBits=function(){return this.to(s.bits)},s.prototype.toSatoshis=function(){return this.to(s.satoshis)},s.prototype.atRate=function(e){return this.to(e)},s.prototype.toString=function(){return this.satoshis+" satoshis"},s.prototype.toObject=s.prototype.toJSON=function(){return{amount:this.BTC,code:s.BTC}},s.prototype.inspect=function(){return""},t.exports=s},{"./errors":97,"./util/preconditions":126,lodash:318}],123:[function(e,t,r){"use strict";function i(e,t){if(!(this instanceof i))return new i(e,t);if(this.extras={},this.knownParams=t||[],this.address=this.network=this.amount=this.message=null,"string"==typeof e){t=i.parse(e);t.amount&&(t.amount=this._parseAmount(t.amount)),this._fromObject(t)}else{if("object"!==_typeof(e))throw new TypeError("Unrecognized data format.");this._fromObject(e)}}var n=e("lodash"),a=e("url"),o=e("./address"),s=e("./unit");i.fromString=function(e){if("string"!=typeof e)throw new TypeError("Expected a string");return new i(e)},i.fromObject=function(e){return new i(e)},i.isValid=function(e,t){try{new i(e,t)}catch(e){return!1}return!0},i.parse=function(e){var t=a.parse(e,!0);if("bitcoin:"!==t.protocol)throw new TypeError("Invalid bitcoin URI");e=/[^:]*:\/?\/?([^?]*)/.exec(e);return t.query.address=e&&e[1]||void 0,t.query},i.Members=["address","amount","message","label","r"],i.prototype._fromObject=function(e){if(!o.isValid(e.address))throw new TypeError("Invalid bitcoin address");for(var t in this.address=new o(e.address),this.network=this.address.network,this.amount=e.amount,e)if("address"!==t&&"amount"!==t){if(/^req-/.exec(t)&&-1===this.knownParams.indexOf(t))throw Error("Unknown required argument "+t);(-1"},t.exports=i},{"./address":80,"./unit":122,lodash:318,url:476}],124:[function(r,a,e){(function(i){(function(){"use strict";var t=r("buffer"),n=(r("assert"),r("./js"),r("./preconditions"));function e(e,t){if(e.length!==t.length)return!1;for(var r=e.length,i=0;i>24&255),t.push(e>>16&255),t.push(e>>8&255),t.push(255&e),i.from(t)},integerFromBuffer:function(e){return n.checkArgumentType(e,"Buffer","buffer"),e[0]<<24|e[1]<<16|e[2]<<8|e[3]},integerFromSingleByteBuffer:function(e){return n.checkArgumentType(e,"Buffer","buffer"),e[0]},bufferToHex:function(e){return n.checkArgumentType(e,"Buffer","buffer"),e.toString("hex")},reverse:function(e){return i.from(e).reverse()}},a.exports.NULL_HASH=a.exports.fill(i.alloc(32),0),a.exports.EMPTY_BUFFER=i.alloc(0)}).call(this)}).call(this,r("buffer").Buffer)},{"./js":125,"./preconditions":126,assert:68,buffer:186}],125:[function(e,t,r){"use strict";var i=e("lodash"),e=function(e){return!!i.isString(e)&&/^[0-9a-fA-F]+$/.test(e)};t.exports={isValidJSON:function(e){var t;if(!i.isString(e))return!1;try{t=JSON.parse(e)}catch(e){return!1}return"object"===_typeof(t)},isHexa:e,isHexaString:e,cloneArray:function(e){return[].concat(e)},defineImmutable:function(t,r){return Object.keys(r).forEach(function(e){Object.defineProperty(t,e,{configurable:!1,enumerable:!0,value:r[e]})}),t},isNaturalNumber:function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e&&0<=e}}},{lodash:318}],126:[function(i,e,t){"use strict";var n=i("../errors"),a=i("lodash");e.exports={checkState:function(e,t){if(!e)throw new n.InvalidState(t)},checkArgument:function(e,t,r,i){if(!e)throw new n.InvalidArgument(t,r,i)},checkArgumentType:function(e,t,r){if(r=r||"(unknown name)",a.isString(t)){if("Buffer"===t){if(!i("buffer").Buffer.isBuffer(e))throw new n.InvalidArgumentType(e,t,r)}else if(_typeof(e)!==t)throw new n.InvalidArgumentType(e,t,r)}else if(!(e instanceof t))throw new n.InvalidArgumentType(e,t.name,r)}}},{"../errors":97,buffer:186,lodash:318}],127:[function(e,t,r){t.exports={_from:"bitcore-lib@^8.14.4",_id:"bitcore-lib@8.24.2",_inBundle:!1,_integrity:"sha512-jujnK/wsLs4ARe3VEfZmbzNrPRgLoirz7PYJn4uRVk2vP7zeiN8pStnbYUNSB0ZgNnB7lcB1F3ZnSBk2y1By/Q==",_location:"/bitcore-lib",_phantomChildren:{},_requested:{type:"range",registry:!0,raw:"bitcore-lib@^8.14.4",name:"bitcore-lib",escapedName:"bitcore-lib",rawSpec:"^8.14.4",saveSpec:null,fetchSpec:"^8.14.4"},_requiredBy:["/"],_resolved:"https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.24.2.tgz",_shasum:"62d2b5dd6622c1ce6c3edc8945bcee462544ee17",_spec:"bitcore-lib@^8.14.4",_where:"/home/runner/work/javascript-opentimestamps/javascript-opentimestamps",author:{name:"BitPay",email:"dev@bitpay.com"},browser:{request:"browser-request"},bundleDependencies:!1,dependencies:{bech32:"=1.1.3","bn.js":"=4.11.8",bs58:"^4.0.1","buffer-compare":"=1.1.1",elliptic:"^6.5.3",inherits:"=2.0.1",lodash:"^4.17.20"},deprecated:!1,description:"A pure and powerful JavaScript Bitcoin library.",devDependencies:{"bitcore-build":"^8.24.2",brfs:"^2.0.1",chai:"^4.2.0",gulp:"^4.0.0",sinon:"^7.1.1"},gitHead:"012cc0216a9bc6b195035855bd17149bad41acd1",keywords:["bitcoin","transaction","address","p2p","ecies","cryptocurrency","blockchain","payment","bip21","bip32","bip37","bip69","bip70","multisig"],license:"MIT",main:"index.js",name:"bitcore-lib",repository:{type:"git",url:"https://github.com/bitpay/bitcore/tree/master/packages/bitcore-lib"},scripts:{build:"gulp",coverage:"gulp coverage",pub:"npm run build && npm publish",test:"gulp test","test:ci":"npm run test"},version:"8.24.2"}},{}],128:[function(e,r,i){(function(ne,H,s){(function(){var e,t;e=function(){var e,t,r;return function i(n,a,o){function s(r,e){if(!a[r]){if(!n[r]){var t="function"==typeof _dereq_&&_dereq_;if(!e&&t)return t(r,!0);if(u)return u(r,!0);t=new Error("Cannot find module '"+r+"'");throw t.code="MODULE_NOT_FOUND",t}t=a[r]={exports:{}};n[r][0].call(t.exports,function(e){var t=n[r][1][e];return s(t||e)},t,t.exports,i,n,a,o)}return a[r].exports}for(var u="function"==typeof _dereq_&&_dereq_,e=0;e, no stack trace)"}function Y(){return"function"==typeof te}var Q=function(){return!1},X=/[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;function J(e){e=e.match(X);if(e)return{fileName:e[1],line:parseInt(e[2],10)}}function ee(e){this._parent=e,this._promisesCreated=0;e=this._length=1+(void 0===e?0:e._length);te(this,ee),32=a)return r[t]=e,this._queue.push(t),!1;null!==n&&(n[t]=e);var o=this._promise,s=this._callback,u=o._boundValue();o._pushContext();u=l(s).call(u,e,t,i),e=o._popContext();if(p.checkForgottenReturns(u,e,null!==n?"Promise.filter":"Promise.map",o),u===h)return this._reject(u.e),!0;e=f(u,this._promise);if(e instanceof c){o=(e=e._target())._bitField;if(0==(50397184&o))return 1<=a&&this._inFlight++,(r[t]=e)._proxy(this,-1*(t+1)),!1;if(0==(33554432&o))return 0!=(16777216&o)?this._reject(e._reason()):this._cancel(),!0;u=e._value()}r[t]=u}return i<=++this._totalResolved&&(null!==n?this._filter(r,n):this._resolve(r),!0)},o.prototype._drainQueue=function(){for(var e=this._queue,t=this._limit,r=this._values;0>2^134217728)},I.prototype._setNoAsyncGuarantee=function(){this._bitField=-134217729&(536870912|this._bitField)},I.prototype._receiverAt=function(e){e=0===e?this._receiver0:this[4*e-4+3];if(e!==a)return void 0===e&&this._isBound()?this._boundValue():e},I.prototype._promiseAt=function(e){return this[4*e-4+2]},I.prototype._fulfillmentHandlerAt=function(e){return this[4*e-4]},I.prototype._rejectionHandlerAt=function(e){return this[4*e-4+1]},I.prototype._boundValue=function(){},I.prototype._migrateCallback0=function(e){e._bitField;var t=e._fulfillmentHandler0,r=e._rejectionHandler0,i=e._promise0,e=e._receiverAt(0);void 0===e&&(e=a),this._addCallbacks(t,r,i,e,null)},I.prototype._migrateCallbackAt=function(e,t){var r=e._fulfillmentHandlerAt(t),i=e._rejectionHandlerAt(t),n=e._promiseAt(t),t=e._receiverAt(t);void 0===t&&(t=a),this._addCallbacks(r,i,n,t,null)},I.prototype._addCallbacks=function(e,t,r,i,n){var a,o=this._length();return 65531<=o&&(o=0,this._setLength(0)),0===o?(this._promise0=r,this._receiver0=i,"function"==typeof e&&(this._fulfillmentHandler0=p.contextBind(n,e)),"function"==typeof t&&(this._rejectionHandler0=p.contextBind(n,t))):(this[2+(a=4*o-4)]=r,this[3+a]=i,"function"==typeof e&&(this[a]=p.contextBind(n,e)),"function"==typeof t&&(this[1+a]=p.contextBind(n,t))),this._setLength(o+1),o},I.prototype._proxy=function(e,t){this._addCallbacks(void 0,void 0,t,e,null)},I.prototype._resolveCallback=function(e,t){if(0==(117506048&this._bitField)){if(e===this)return this._rejectCallback(o(),!1);var r=_(e,this);if(!(r instanceof I))return this._fulfill(e);t&&this._propagateFrom(r,2);var i=r._target();if(i!==this){t=i._bitField;if(0==(50397184&t)){var n=this._length();0>>16)){if(e===this){var r=o();return this._attachExtraTrace(r),this._reject(r)}this._setFulfilled(),this._rejectionHandler0=e,0<(65535&t)&&(0!=(134217728&t)?this._settlePromises():h.settlePromises(this),this._dereferenceTrace())}},I.prototype._reject=function(e){var t=this._bitField;if(!((117506048&t)>>>16)){if(this._setRejected(),this._fulfillmentHandler0=e,this._isFinal())return h.fatalError(e,p.isNode);0<(65535&t)?h.settlePromises(this):this._ensurePossibleRejectionHandled()}},I.prototype._fulfillPromises=function(e,t){for(var r=1;r=this._length&&(this._resolve(this._values),!0)},t.prototype._promiseCancelled=function(){return this._cancel(),!0},t.prototype._promiseRejected=function(e){return this._totalResolved++,this._reject(e),!0},t.prototype._resultCancelled=function(){if(!this._isResolved()){var e=this._values;if(this._cancel(),e instanceof s)e.cancel();else for(var t=0;t=this._length){if(this._isMap)r=function(e){for(var t=new s,r=e.length/2|0,i=0;i>1},r.prototype.props=function(){return h(this)},r.props=h}},{"./es5":13,"./util":36}],26:[function(e,t,r){"use strict";function i(e){this._capacity=e,this._length=0,this._front=0}i.prototype._willBeOverCapacity=function(e){return this._capacity=this._length&&(this._resolve(this._values),!0)},n.prototype._promiseFulfilled=function(e,t){var r=new i;return r._bitField=33554432,r._settledValueField=e,this._promiseResolved(t,r)},n.prototype._promiseRejected=function(e,t){var r=new i;return r._bitField=16777216,r._settledValueField=e,this._promiseResolved(t,r)},e.settle=function(e){return r.deprecated(".settle()",".reflect()"),new n(e).promise()},e.allSettled=function(e){return new n(e).promise()},e.prototype.settle=function(){return e.settle(this)}}},{"./util":36}],31:[function(f,e,t){"use strict";e.exports=function(e,t,i){var r=f("./util"),n=f("./errors").RangeError,a=f("./errors").AggregateError,o=r.isArray,s={};function u(e){this.constructor$(e),this._howMany=0,this._unwrap=!1,this._initialized=!1}function c(e,t){if((0|t)!==t||t<0)return i("expecting a positive integer\n\n See http://goo.gl/MqrFmX\n");var r=new u(e),e=r.promise();return r.setHowMany(t),r.init(),e}r.inherits(u,t),u.prototype._init=function(){var e;this._initialized&&(0!==this._howMany?(this._init$(void 0,-5),e=o(this._values),!this._isResolved()&&e&&this._howMany>this._canPossiblyFulfill()&&this._reject(this._getRangeError(this.length()))):this._resolve([]))},u.prototype.init=function(){this._initialized=!0,this._init()},u.prototype.setUnwrap=function(){this._unwrap=!0},u.prototype.howMany=function(){return this._howMany},u.prototype.setHowMany=function(e){this._howMany=e},u.prototype._promiseFulfilled=function(e){return this._addFulfilled(e),this._fulfilled()===this.howMany()&&(this._values.length=this.howMany(),1===this.howMany()&&this._unwrap?this._resolve(this._values[0]):this._resolve(this._values),!0)},u.prototype._promiseRejected=function(e){return this._addRejected(e),this._checkOutcome()},u.prototype._promiseCancelled=function(){return this._values instanceof e||null==this._values?this._cancel():(this._addRejected(s),this._checkOutcome())},u.prototype._checkOutcome=function(){if(this.howMany()>this._canPossiblyFulfill()){for(var e=new a,t=this.length();t>>26-o&67108863,26<=(o+=24)&&(o-=26,i++);else if("le"===r)for(i=a=0;a>>26-o&67108863,26<=(o+=24)&&(o-=26,i++);return this.strip()},g.prototype._parseHex=function(e,t){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var r,i=0;i>>26-n&4194303,26<=(n+=24)&&(n-=26,a++);i+6!==t&&(r=o(e,t,i+6),this.words[a]|=r<>>26-n&4194303),this.strip()},g.prototype._parseBase=function(e,t,r){this.words=[0];for(var i=0,n=this.length=1;n<=67108863;n*=t)i++;i--,n=n/t|0;for(var a=e.length-r,o=a%i,s=Math.min(a,a-o)+r,u=0,c=r;c"};var l=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],h=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],d=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function n(e,t,r){r.negative=t.negative^e.negative;var i=e.length+t.length|0,i=(r.length=i)-1|0,n=67108863&(p=(0|e.words[0])*(0|t.words[0])),a=p/67108864|0;r.words[0]=n;for(var o=1;o>>26,u=67108863&a,c=Math.min(o,t.length-1),f=Math.max(0,o-e.length+1);f<=c;f++){var p,l=o-f|0;s+=(p=(0|e.words[l])*(0|t.words[f])+u)/67108864|0,u=67108863&p}r.words[o]=0|u,a=0|s}return 0!==a?r.words[o]=0|a:r.length--,r.strip()}g.prototype.toString=function(e,t){if(t=0|t||1,16===(e=e||10)||"hex"===e){s="";for(var r=0,i=0,n=0;n>>24-r&16777215)||n!==this.length-1?l[6-o.length]+o+s:o+s;26<=(r+=2)&&(r-=26,n--)}for(0!==i&&(s=i.toString(16)+s);s.length%t!=0;)s="0"+s;return s=0!==this.negative?"-"+s:s}if(e===(0|e)&&2<=e&&e<=36){var u=h[e],c=d[e];for(s="",(f=this.clone()).negative=0;!f.isZero();){var f,p=f.modn(c).toString(e);s=(f=f.idivn(c)).isZero()?p+s:l[u-p.length]+p+s}for(this.isZero()&&(s="0"+s);s.length%t!=0;)s="0"+s;return s=0!==this.negative?"-"+s:s}m(!1,"Base should be between 2 and 36")},g.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:2>>=13),64<=t&&(e+=7,t>>>=7),8<=t&&(e+=4,t>>>=4),2<=t&&(e+=2,t>>>=2),e+t},g.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,e=0;return 0==(8191&t)&&(e+=13,t>>>=13),0==(127&t)&&(e+=7,t>>>=7),0==(15&t)&&(e+=4,t>>>=4),0==(3&t)&&(e+=2,t>>>=2),0==(1&t)&&e++,e},g.prototype.bitLength=function(){var e=this.words[this.length-1],e=this._countBits(e);return 26*(this.length-1)+e},g.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;te.length?this.clone().ior(e):e.clone().ior(this)},g.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},g.prototype.iuand=function(e){for(var t=this.length>e.length?e:this,r=0;re.length?this.clone().iand(e):e.clone().iand(this)},g.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},g.prototype.iuxor=function(e){for(var t,r=this.length>e.length?(t=this,e):(t=e,this),i=0;ie.length?this.clone().ixor(e):e.clone().ixor(this)},g.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},g.prototype.inotn=function(e){m("number"==typeof e&&0<=e);var t=0|Math.ceil(e/26),e=e%26;this._expand(t),0>26-e),this.strip()},g.prototype.notn=function(e){return this.clone().inotn(e)},g.prototype.setn=function(e,t){m("number"==typeof e&&0<=e);var r=e/26|0,e=e%26;return this._expand(1+r),this.words[r]=t?this.words[r]|1<e.length?(r=this,e):(r=e,this);for(var n=0,a=0;a>>26;for(;0!==n&&a>>26;if(this.length=r.length,0!==n)this.words[this.length]=n,this.length++;else if(r!==this)for(;ae.length?this.clone().iadd(e):e.clone().iadd(this)},g.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var r,i,n=this.cmp(e);if(0===n)return this.negative=0,this.length=1,this.words[0]=0,this;i=0>26,this.words[o]=67108863&t;for(;0!==a&&o>26,this.words[o]=67108863&t;if(0===a&&o>>13,c=0|i[1],f=8191&c,p=c>>>13,l=0|i[2],h=8191&l,d=l>>>13,m=0|i[3],g=8191&m,b=m>>>13,y=0|i[4],v=8191&y,_=y>>>13,w=0|i[5],k=8191&w,x=w>>>13,S=0|i[6],j=8191&S,E=S>>>13,A=0|i[7],P=8191&A,I=A>>>13,T=0|i[8],O=8191&T,C=T>>>13,R=0|i[9],B=8191&R,F=R>>>13,M=0|n[0],z=8191&M,N=M>>>13,D=0|n[1],L=8191&D,q=D>>>13,U=0|n[2],H=8191&U,K=U>>>13,V=0|n[3],$=8191&V,G=V>>>13,W=0|n[4],Z=8191&W,Y=W>>>13,Q=0|n[5],X=8191&Q,J=Q>>>13,o=0|n[6],c=8191&o,l=o>>>13,m=0|n[7],y=8191&m,w=m>>>13,S=0|n[8],A=8191&S,T=S>>>13,i=0|n[9],R=8191&i,M=i>>>13;r.negative=e.negative^t.negative,r.length=19;var V=(0+Math.imul(s,z)|0)+((8191&(U=Math.imul(s,N)+Math.imul(u,z)|0))<<13)|0,ee=(Math.imul(u,N)+(U>>>13)|0)+(V>>>26)|0;V&=67108863,D=Math.imul(f,z),U=Math.imul(f,N)+Math.imul(p,z)|0,W=Math.imul(p,N);Q=(ee+(D+Math.imul(s,L)|0)|0)+((8191&(U=(U+Math.imul(s,q)|0)+Math.imul(u,L)|0))<<13)|0;ee=((W+Math.imul(u,q)|0)+(U>>>13)|0)+(Q>>>26)|0,Q&=67108863,D=Math.imul(h,z),U=Math.imul(h,N)+Math.imul(d,z)|0,W=Math.imul(d,N),D=D+Math.imul(f,L)|0,U=(U+Math.imul(f,q)|0)+Math.imul(p,L)|0,W=W+Math.imul(p,q)|0;o=(ee+(D+Math.imul(s,H)|0)|0)+((8191&(U=(U+Math.imul(s,K)|0)+Math.imul(u,H)|0))<<13)|0;ee=((W+Math.imul(u,K)|0)+(U>>>13)|0)+(o>>>26)|0,o&=67108863,D=Math.imul(g,z),U=Math.imul(g,N)+Math.imul(b,z)|0,W=Math.imul(b,N),D=D+Math.imul(h,L)|0,U=(U+Math.imul(h,q)|0)+Math.imul(d,L)|0,W=W+Math.imul(d,q)|0,D=D+Math.imul(f,H)|0,U=(U+Math.imul(f,K)|0)+Math.imul(p,H)|0,W=W+Math.imul(p,K)|0;m=(ee+(D+Math.imul(s,$)|0)|0)+((8191&(U=(U+Math.imul(s,G)|0)+Math.imul(u,$)|0))<<13)|0;ee=((W+Math.imul(u,G)|0)+(U>>>13)|0)+(m>>>26)|0,m&=67108863,D=Math.imul(v,z),U=Math.imul(v,N)+Math.imul(_,z)|0,W=Math.imul(_,N),D=D+Math.imul(g,L)|0,U=(U+Math.imul(g,q)|0)+Math.imul(b,L)|0,W=W+Math.imul(b,q)|0,D=D+Math.imul(h,H)|0,U=(U+Math.imul(h,K)|0)+Math.imul(d,H)|0,W=W+Math.imul(d,K)|0,D=D+Math.imul(f,$)|0,U=(U+Math.imul(f,G)|0)+Math.imul(p,$)|0,W=W+Math.imul(p,G)|0;S=(ee+(D+Math.imul(s,Z)|0)|0)+((8191&(U=(U+Math.imul(s,Y)|0)+Math.imul(u,Z)|0))<<13)|0;ee=((W+Math.imul(u,Y)|0)+(U>>>13)|0)+(S>>>26)|0,S&=67108863,D=Math.imul(k,z),U=Math.imul(k,N)+Math.imul(x,z)|0,W=Math.imul(x,N),D=D+Math.imul(v,L)|0,U=(U+Math.imul(v,q)|0)+Math.imul(_,L)|0,W=W+Math.imul(_,q)|0,D=D+Math.imul(g,H)|0,U=(U+Math.imul(g,K)|0)+Math.imul(b,H)|0,W=W+Math.imul(b,K)|0,D=D+Math.imul(h,$)|0,U=(U+Math.imul(h,G)|0)+Math.imul(d,$)|0,W=W+Math.imul(d,G)|0,D=D+Math.imul(f,Z)|0,U=(U+Math.imul(f,Y)|0)+Math.imul(p,Z)|0,W=W+Math.imul(p,Y)|0;n=(ee+(D+Math.imul(s,X)|0)|0)+((8191&(U=(U+Math.imul(s,J)|0)+Math.imul(u,X)|0))<<13)|0;ee=((W+Math.imul(u,J)|0)+(U>>>13)|0)+(n>>>26)|0,n&=67108863,D=Math.imul(j,z),U=Math.imul(j,N)+Math.imul(E,z)|0,W=Math.imul(E,N),D=D+Math.imul(k,L)|0,U=(U+Math.imul(k,q)|0)+Math.imul(x,L)|0,W=W+Math.imul(x,q)|0,D=D+Math.imul(v,H)|0,U=(U+Math.imul(v,K)|0)+Math.imul(_,H)|0,W=W+Math.imul(_,K)|0,D=D+Math.imul(g,$)|0,U=(U+Math.imul(g,G)|0)+Math.imul(b,$)|0,W=W+Math.imul(b,G)|0,D=D+Math.imul(h,Z)|0,U=(U+Math.imul(h,Y)|0)+Math.imul(d,Z)|0,W=W+Math.imul(d,Y)|0,D=D+Math.imul(f,X)|0,U=(U+Math.imul(f,J)|0)+Math.imul(p,X)|0,W=W+Math.imul(p,J)|0;i=(ee+(D+Math.imul(s,c)|0)|0)+((8191&(U=(U+Math.imul(s,l)|0)+Math.imul(u,c)|0))<<13)|0;ee=((W+Math.imul(u,l)|0)+(U>>>13)|0)+(i>>>26)|0,i&=67108863,D=Math.imul(P,z),U=Math.imul(P,N)+Math.imul(I,z)|0,W=Math.imul(I,N),D=D+Math.imul(j,L)|0,U=(U+Math.imul(j,q)|0)+Math.imul(E,L)|0,W=W+Math.imul(E,q)|0,D=D+Math.imul(k,H)|0,U=(U+Math.imul(k,K)|0)+Math.imul(x,H)|0,W=W+Math.imul(x,K)|0,D=D+Math.imul(v,$)|0,U=(U+Math.imul(v,G)|0)+Math.imul(_,$)|0,W=W+Math.imul(_,G)|0,D=D+Math.imul(g,Z)|0,U=(U+Math.imul(g,Y)|0)+Math.imul(b,Z)|0,W=W+Math.imul(b,Y)|0,D=D+Math.imul(h,X)|0,U=(U+Math.imul(h,J)|0)+Math.imul(d,X)|0,W=W+Math.imul(d,J)|0,D=D+Math.imul(f,c)|0,U=(U+Math.imul(f,l)|0)+Math.imul(p,c)|0,W=W+Math.imul(p,l)|0;e=(ee+(D+Math.imul(s,y)|0)|0)+((8191&(U=(U+Math.imul(s,w)|0)+Math.imul(u,y)|0))<<13)|0;ee=((W+Math.imul(u,w)|0)+(U>>>13)|0)+(e>>>26)|0,e&=67108863,D=Math.imul(O,z),U=Math.imul(O,N)+Math.imul(C,z)|0,W=Math.imul(C,N),D=D+Math.imul(P,L)|0,U=(U+Math.imul(P,q)|0)+Math.imul(I,L)|0,W=W+Math.imul(I,q)|0,D=D+Math.imul(j,H)|0,U=(U+Math.imul(j,K)|0)+Math.imul(E,H)|0,W=W+Math.imul(E,K)|0,D=D+Math.imul(k,$)|0,U=(U+Math.imul(k,G)|0)+Math.imul(x,$)|0,W=W+Math.imul(x,G)|0,D=D+Math.imul(v,Z)|0,U=(U+Math.imul(v,Y)|0)+Math.imul(_,Z)|0,W=W+Math.imul(_,Y)|0,D=D+Math.imul(g,X)|0,U=(U+Math.imul(g,J)|0)+Math.imul(b,X)|0,W=W+Math.imul(b,J)|0,D=D+Math.imul(h,c)|0,U=(U+Math.imul(h,l)|0)+Math.imul(d,c)|0,W=W+Math.imul(d,l)|0,D=D+Math.imul(f,y)|0,U=(U+Math.imul(f,w)|0)+Math.imul(p,y)|0,W=W+Math.imul(p,w)|0;t=(ee+(D+Math.imul(s,A)|0)|0)+((8191&(U=(U+Math.imul(s,T)|0)+Math.imul(u,A)|0))<<13)|0;ee=((W+Math.imul(u,T)|0)+(U>>>13)|0)+(t>>>26)|0,t&=67108863,D=Math.imul(B,z),U=Math.imul(B,N)+Math.imul(F,z)|0,W=Math.imul(F,N),D=D+Math.imul(O,L)|0,U=(U+Math.imul(O,q)|0)+Math.imul(C,L)|0,W=W+Math.imul(C,q)|0,D=D+Math.imul(P,H)|0,U=(U+Math.imul(P,K)|0)+Math.imul(I,H)|0,W=W+Math.imul(I,K)|0,D=D+Math.imul(j,$)|0,U=(U+Math.imul(j,G)|0)+Math.imul(E,$)|0,W=W+Math.imul(E,G)|0,D=D+Math.imul(k,Z)|0,U=(U+Math.imul(k,Y)|0)+Math.imul(x,Z)|0,W=W+Math.imul(x,Y)|0,D=D+Math.imul(v,X)|0,U=(U+Math.imul(v,J)|0)+Math.imul(_,X)|0,W=W+Math.imul(_,J)|0,D=D+Math.imul(g,c)|0,U=(U+Math.imul(g,l)|0)+Math.imul(b,c)|0,W=W+Math.imul(b,l)|0,D=D+Math.imul(h,y)|0,U=(U+Math.imul(h,w)|0)+Math.imul(d,y)|0,W=W+Math.imul(d,w)|0,D=D+Math.imul(f,A)|0,U=(U+Math.imul(f,T)|0)+Math.imul(p,A)|0,W=W+Math.imul(p,T)|0;s=(ee+(D+Math.imul(s,R)|0)|0)+((8191&(U=(U+Math.imul(s,M)|0)+Math.imul(u,R)|0))<<13)|0;ee=((W+Math.imul(u,M)|0)+(U>>>13)|0)+(s>>>26)|0,s&=67108863,D=Math.imul(B,L),U=Math.imul(B,q)+Math.imul(F,L)|0,W=Math.imul(F,q),D=D+Math.imul(O,H)|0,U=(U+Math.imul(O,K)|0)+Math.imul(C,H)|0,W=W+Math.imul(C,K)|0,D=D+Math.imul(P,$)|0,U=(U+Math.imul(P,G)|0)+Math.imul(I,$)|0,W=W+Math.imul(I,G)|0,D=D+Math.imul(j,Z)|0,U=(U+Math.imul(j,Y)|0)+Math.imul(E,Z)|0,W=W+Math.imul(E,Y)|0,D=D+Math.imul(k,X)|0,U=(U+Math.imul(k,J)|0)+Math.imul(x,X)|0,W=W+Math.imul(x,J)|0,D=D+Math.imul(v,c)|0,U=(U+Math.imul(v,l)|0)+Math.imul(_,c)|0,W=W+Math.imul(_,l)|0,D=D+Math.imul(g,y)|0,U=(U+Math.imul(g,w)|0)+Math.imul(b,y)|0,W=W+Math.imul(b,w)|0,D=D+Math.imul(h,A)|0,U=(U+Math.imul(h,T)|0)+Math.imul(d,A)|0,W=W+Math.imul(d,T)|0;f=(ee+(D+Math.imul(f,R)|0)|0)+((8191&(U=(U+Math.imul(f,M)|0)+Math.imul(p,R)|0))<<13)|0;ee=((W+Math.imul(p,M)|0)+(U>>>13)|0)+(f>>>26)|0,f&=67108863,D=Math.imul(B,H),U=Math.imul(B,K)+Math.imul(F,H)|0,W=Math.imul(F,K),D=D+Math.imul(O,$)|0,U=(U+Math.imul(O,G)|0)+Math.imul(C,$)|0,W=W+Math.imul(C,G)|0,D=D+Math.imul(P,Z)|0,U=(U+Math.imul(P,Y)|0)+Math.imul(I,Z)|0,W=W+Math.imul(I,Y)|0,D=D+Math.imul(j,X)|0,U=(U+Math.imul(j,J)|0)+Math.imul(E,X)|0,W=W+Math.imul(E,J)|0,D=D+Math.imul(k,c)|0,U=(U+Math.imul(k,l)|0)+Math.imul(x,c)|0,W=W+Math.imul(x,l)|0,D=D+Math.imul(v,y)|0,U=(U+Math.imul(v,w)|0)+Math.imul(_,y)|0,W=W+Math.imul(_,w)|0,D=D+Math.imul(g,A)|0,U=(U+Math.imul(g,T)|0)+Math.imul(b,A)|0,W=W+Math.imul(b,T)|0;h=(ee+(D+Math.imul(h,R)|0)|0)+((8191&(U=(U+Math.imul(h,M)|0)+Math.imul(d,R)|0))<<13)|0;ee=((W+Math.imul(d,M)|0)+(U>>>13)|0)+(h>>>26)|0,h&=67108863,D=Math.imul(B,$),U=Math.imul(B,G)+Math.imul(F,$)|0,W=Math.imul(F,G),D=D+Math.imul(O,Z)|0,U=(U+Math.imul(O,Y)|0)+Math.imul(C,Z)|0,W=W+Math.imul(C,Y)|0,D=D+Math.imul(P,X)|0,U=(U+Math.imul(P,J)|0)+Math.imul(I,X)|0,W=W+Math.imul(I,J)|0,D=D+Math.imul(j,c)|0,U=(U+Math.imul(j,l)|0)+Math.imul(E,c)|0,W=W+Math.imul(E,l)|0,D=D+Math.imul(k,y)|0,U=(U+Math.imul(k,w)|0)+Math.imul(x,y)|0,W=W+Math.imul(x,w)|0,D=D+Math.imul(v,A)|0,U=(U+Math.imul(v,T)|0)+Math.imul(_,A)|0,W=W+Math.imul(_,T)|0;g=(ee+(D+Math.imul(g,R)|0)|0)+((8191&(U=(U+Math.imul(g,M)|0)+Math.imul(b,R)|0))<<13)|0;ee=((W+Math.imul(b,M)|0)+(U>>>13)|0)+(g>>>26)|0,g&=67108863,D=Math.imul(B,Z),U=Math.imul(B,Y)+Math.imul(F,Z)|0,W=Math.imul(F,Y),D=D+Math.imul(O,X)|0,U=(U+Math.imul(O,J)|0)+Math.imul(C,X)|0,W=W+Math.imul(C,J)|0,D=D+Math.imul(P,c)|0,U=(U+Math.imul(P,l)|0)+Math.imul(I,c)|0,W=W+Math.imul(I,l)|0,D=D+Math.imul(j,y)|0,U=(U+Math.imul(j,w)|0)+Math.imul(E,y)|0,W=W+Math.imul(E,w)|0,D=D+Math.imul(k,A)|0,U=(U+Math.imul(k,T)|0)+Math.imul(x,A)|0,W=W+Math.imul(x,T)|0;v=(ee+(D+Math.imul(v,R)|0)|0)+((8191&(U=(U+Math.imul(v,M)|0)+Math.imul(_,R)|0))<<13)|0;ee=((W+Math.imul(_,M)|0)+(U>>>13)|0)+(v>>>26)|0,v&=67108863,D=Math.imul(B,X),U=Math.imul(B,J)+Math.imul(F,X)|0,W=Math.imul(F,J),D=D+Math.imul(O,c)|0,U=(U+Math.imul(O,l)|0)+Math.imul(C,c)|0,W=W+Math.imul(C,l)|0,D=D+Math.imul(P,y)|0,U=(U+Math.imul(P,w)|0)+Math.imul(I,y)|0,W=W+Math.imul(I,w)|0,D=D+Math.imul(j,A)|0,U=(U+Math.imul(j,T)|0)+Math.imul(E,A)|0,W=W+Math.imul(E,T)|0;k=(ee+(D+Math.imul(k,R)|0)|0)+((8191&(U=(U+Math.imul(k,M)|0)+Math.imul(x,R)|0))<<13)|0;ee=((W+Math.imul(x,M)|0)+(U>>>13)|0)+(k>>>26)|0,k&=67108863,D=Math.imul(B,c),U=Math.imul(B,l)+Math.imul(F,c)|0,W=Math.imul(F,l),D=D+Math.imul(O,y)|0,U=(U+Math.imul(O,w)|0)+Math.imul(C,y)|0,W=W+Math.imul(C,w)|0,D=D+Math.imul(P,A)|0,U=(U+Math.imul(P,T)|0)+Math.imul(I,A)|0,W=W+Math.imul(I,T)|0;j=(ee+(D+Math.imul(j,R)|0)|0)+((8191&(U=(U+Math.imul(j,M)|0)+Math.imul(E,R)|0))<<13)|0;ee=((W+Math.imul(E,M)|0)+(U>>>13)|0)+(j>>>26)|0,j&=67108863,D=Math.imul(B,y),U=Math.imul(B,w)+Math.imul(F,y)|0,W=Math.imul(F,w),D=D+Math.imul(O,A)|0,U=(U+Math.imul(O,T)|0)+Math.imul(C,A)|0,W=W+Math.imul(C,T)|0;P=(ee+(D+Math.imul(P,R)|0)|0)+((8191&(U=(U+Math.imul(P,M)|0)+Math.imul(I,R)|0))<<13)|0;ee=((W+Math.imul(I,M)|0)+(U>>>13)|0)+(P>>>26)|0,P&=67108863,D=Math.imul(B,A),U=Math.imul(B,T)+Math.imul(F,A)|0,W=Math.imul(F,T);O=(ee+(D+Math.imul(O,R)|0)|0)+((8191&(U=(U+Math.imul(O,M)|0)+Math.imul(C,R)|0))<<13)|0;ee=((W+Math.imul(C,M)|0)+(U>>>13)|0)+(O>>>26)|0,O&=67108863;R=(ee+Math.imul(B,R)|0)+((8191&(U=Math.imul(B,M)+Math.imul(F,R)|0))<<13)|0;return ee=(Math.imul(F,M)+(U>>>13)|0)+(R>>>26)|0,R&=67108863,a[0]=V,a[1]=Q,a[2]=o,a[3]=m,a[4]=S,a[5]=n,a[6]=i,a[7]=e,a[8]=t,a[9]=s,a[10]=f,a[11]=h,a[12]=g,a[13]=v,a[14]=k,a[15]=j,a[16]=P,a[17]=O,a[18]=R,0!=ee&&(a[19]=ee,r.length++),r};function s(e,t,r){return(new u).mulp(e,t,r)}function u(e,t){this.x=e,this.y=t}Math.imul||(a=n),g.prototype.mulTo=function(e,t){var r=this.length+e.length,t=(10===this.length&&10===e.length?a:r<63?n:r<1024?function(e,t,r){r.negative=t.negative^e.negative,r.length=e.length+t.length;for(var i=0,n=0,a=0;a>>26)|0)>>>26,o&=67108863}r.words[a]=s,i=o,o=n}return 0!==i?r.words[a]=i:r.length--,r.strip()}:s)(this,e,t);return t},u.prototype.makeRBT=function(e){for(var t=new Array(e),r=g.prototype._countBits(e)-1,i=0;i>=1;return i},u.prototype.permute=function(e,t,r,i,n,a){for(var o=0;o>>=1)r++;return 1<>>=13,r[2*a+1]=8191&n,n>>>=13;for(a=2*t;a>=26,t+=i/67108864|0,t+=n>>>26,this.words[r]=67108863&n}return 0!==t&&(this.words[r]=t,this.length++),this},g.prototype.muln=function(e){return this.clone().imuln(e)},g.prototype.sqr=function(){return this.mul(this)},g.prototype.isqr=function(){return this.imul(this.clone())},g.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),r=0;r>>n}return t}(e);if(0===t.length)return new g(1);for(var r=this,i=0;i>>26-t<<26-t;if(0!=t){for(var n=0,a=0;a>>26-t}n&&(this.words[a]=n,this.length++)}if(0!=r){for(a=this.length-1;0<=a;a--)this.words[a+r]=this.words[a];for(a=0;a>>n<a)for(this.length-=a,u=0;u>>n,c=f&o}return s&&0!==c&&(s.words[s.length++]=c),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},g.prototype.ishrn=function(e,t,r){return m(0===this.negative),this.iushrn(e,t,r)},g.prototype.shln=function(e){return this.clone().ishln(e)},g.prototype.ushln=function(e){return this.clone().iushln(e)},g.prototype.shrn=function(e){return this.clone().ishrn(e)},g.prototype.ushrn=function(e){return this.clone().iushrn(e)},g.prototype.testn=function(e){m("number"==typeof e&&0<=e);var t=e%26,e=(e-t)/26,t=1<>>t<>26)-(s/67108864|0);this.words[o+r]=67108863&i}for(;o>26,this.words[o+r]=67108863&i;if(0===a)return this.strip();for(m(-1===a),o=a=0;o>26,this.words[o]=67108863&i;return this.negative=1,this.strip()},g.prototype._wordDiv=function(e,t){var r=this.length-e.length,i=this.clone(),n=e,a=0|n.words[n.length-1];0!=(r=26-this._countBits(a))&&(n=n.ushln(r),i.iushln(r),a=0|n.words[n.length-1]);var o,s=i.length-n.length;if("mod"!==t){(o=new g(null)).length=1+s,o.words=new Array(o.length);for(var u=0;uthis.length||this.cmp(e)<0?{div:new g(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new g(this.modn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new g(this.modn(e.words[0]))}:this._wordDiv(e,t);var i,n,a},g.prototype.div=function(e){return this.divmod(e,"div",!1).div},g.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},g.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},g.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var r=0!==t.div.negative?t.mod.isub(e):t.mod,i=e.ushrn(1),e=e.andln(1),i=r.cmp(i);return i<0||1===e&&0===i?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},g.prototype.modn=function(e){m(e<=67108863);for(var t=(1<<26)%e,r=0,i=this.length-1;0<=i;i--)r=(t*r+(0|this.words[i]))%e;return r},g.prototype.idivn=function(e){m(e<=67108863);for(var t=0,r=this.length-1;0<=r;r--){var i=(0|this.words[r])+67108864*t;this.words[r]=i/e|0,t=i%e}return this.strip()},g.prototype.divn=function(e){return this.clone().idivn(e)},g.prototype.egcd=function(e){m(0===e.negative),m(!e.isZero());for(var t=this,r=e.clone(),t=0!==t.negative?t.umod(e):t.clone(),i=new g(1),n=new g(0),a=new g(0),o=new g(1),s=0;t.isEven()&&r.isEven();)t.iushrn(1),r.iushrn(1),++s;for(var u=r.clone(),c=t.clone();!t.isZero();){for(var f=0,p=1;0==(t.words[0]&p)&&f<26;++f,p<<=1);if(0>>26;n&=67108863,this.words[i]=n}return 0!==r&&(this.words[i]=r,this.length++),this},g.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},g.prototype.cmpn=function(e){var t=e<0;return 0===this.negative||t?0===this.negative&&t?1:(this.strip(),e=1e.length)return 1;if(this.lengththis.n;);e=t>>22,n=a}n>>>=22,0===(e.words[i-10]=n)&&10>>=26,e.words[r]=n,t=i}return 0!==t&&(e.words[e.length++]=t),e},g._prime=function(e){if(c[e])return c[e];var t;if("k256"===e)t=new b;else if("p224"===e)t=new y;else if("p192"===e)t=new v;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new _}return c[e]=t},w.prototype._verify1=function(e){m(0===e.negative,"red works only with positives"),m(e.red,"red works only with red numbers")},w.prototype._verify2=function(e,t){m(0==(e.negative|t.negative),"red works only with positives"),m(e.red&&e.red===t.red,"red works only with red numbers")},w.prototype.imod=function(e){return(this.prime?this.prime.ireduce(e):e.umod(this.m))._forceRed(this)},w.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},w.prototype.add=function(e,t){this._verify2(e,t);t=e.add(t);return 0<=t.cmp(this.m)&&t.isub(this.m),t._forceRed(this)},w.prototype.iadd=function(e,t){this._verify2(e,t);t=e.iadd(t);return 0<=t.cmp(this.m)&&t.isub(this.m),t},w.prototype.sub=function(e,t){this._verify2(e,t);t=e.sub(t);return t.cmpn(0)<0&&t.iadd(this.m),t._forceRed(this)},w.prototype.isub=function(e,t){this._verify2(e,t);t=e.isub(t);return t.cmpn(0)<0&&t.iadd(this.m),t},w.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},w.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},w.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},w.prototype.isqr=function(e){return this.imul(e,e.clone())},w.prototype.sqr=function(e){return this.mul(e,e)},w.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(m(t%2==1),3===t){t=this.m.add(new g(1)).iushrn(2);return this.pow(e,t)}for(var r=this.m.subn(1),i=0;!r.isZero()&&0===r.andln(1);)i++,r.iushrn(1);m(!r.isZero());for(var n=new g(1).toRed(this),a=n.redNeg(),o=this.m.subn(1).iushrn(1),s=new g(2*(s=this.m.bitLength())*s).toRed(this);0!==this.pow(s,o).cmp(a);)s.redIAdd(a);for(var u=this.pow(s,r),c=this.pow(e,r.addn(1).iushrn(1)),f=this.pow(e,r),p=i;0!==f.cmp(n);){for(var l=f,h=0;0!==l.cmp(n);h++)l=l.redSqr();m(h>c&1;n!==r[0]&&(n=this.sqr(n)),0!=f||0!==a?(a<<=1,a|=f,(4===++o||0===i&&0===c)&&(n=this.mul(n,r[a]),a=o=0)):o=0}s=26}return n},w.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},w.prototype.convertFrom=function(e){e=e.clone();return e.red=null,e},g.mont=function(e){return new k(e)},r(k,w),k.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},k.prototype.convertFrom=function(e){e=this.imod(e.mul(this.rinv));return e.red=null,e},k.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;e=e.imul(t),t=e.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),e=e.isub(t).iushrn(this.shift),t=e;return 0<=e.cmp(this.m)?t=e.isub(this.m):e.cmpn(0)<0&&(t=e.iadd(this.m)),t._forceRed(this)},k.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new g(0)._forceRed(this);e=e.mul(t),t=e.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),e=e.isub(t).iushrn(this.shift),t=e;return 0<=e.cmp(this.m)?t=e.isub(this.m):e.cmpn(0)<0&&(t=e.iadd(this.m)),t._forceRed(this)},k.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(void 0===e||e,this)},{buffer:132}],130:[function(e,t,r){var x=e("concat-map"),S=e("balanced-match");t.exports=function(e){if(!e)return[];"{}"===e.substr(0,2)&&(e="\\{\\}"+e.substr(2));return function t(e,r){var i=[];var n=S("{","}",e);if(!n||/\$$/.test(n.pre))return[e];var a=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(n.body);var o=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(n.body);var s=a||o;a=0<=n.body.indexOf(",");if(!s&&!a)return n.post.match(/,.*\}/)?(e=n.pre+"{"+n.body+j+n.post,t(e)):[e];var u;if(s)u=n.body.split(/\.\./);else if(u=A(n.body),1===u.length&&1===(u=t(u[0],!1).map(P)).length){var c=n.post.length?t(n.post,!1):[""];return c.map(function(e){return n.pre+u[0]+e})}var f=n.pre;var c=n.post.length?t(n.post,!1):[""];var p;if(s){var a=E(u[0]),l=E(u[1]),h=Math.max(u[0].length,u[1].length),d=3==u.length?Math.abs(E(u[2])):1,m=T,e=l>>24]^f[d>>>16&255]^p[m>>>8&255]^l[255&g]^t[b++],o=c[d>>>24]^f[m>>>16&255]^p[g>>>8&255]^l[255&h]^t[b++],s=c[m>>>24]^f[g>>>16&255]^p[h>>>8&255]^l[255&d]^t[b++],u=c[g>>>24]^f[h>>>16&255]^p[d>>>8&255]^l[255&m]^t[b++],h=a,d=o,m=s,g=u;return a=(i[h>>>24]<<24|i[d>>>16&255]<<16|i[m>>>8&255]<<8|i[255&g])^t[b++],o=(i[d>>>24]<<24|i[m>>>16&255]<<16|i[g>>>8&255]<<8|i[255&h])^t[b++],s=(i[m>>>24]<<24|i[g>>>16&255]<<16|i[h>>>8&255]<<8|i[255&d])^t[b++],u=(i[g>>>24]<<24|i[h>>>16&255]<<16|i[d>>>8&255]<<8|i[255&m])^t[b++],[a>>>=0,o>>>=0,s>>>=0,u>>>=0]}var p=[0,1,2,4,8,16,32,64,128,27,54],l=function(){for(var e=new Array(256),t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;for(var r=[],i=[],n=[[],[],[],[]],a=[[],[],[],[]],o=0,s=0,u=0;u<256;++u){var c=(c=s^s<<1^s<<2^s<<3^s<<4)>>>8^255&c^99,f=e[i[r[o]=c]=o],p=e[f],l=e[p],h=257*e[c]^16843008*c;n[0][o]=h<<24|h>>>8,n[1][o]=h<<16|h>>>16,n[2][o]=h<<8|h>>>24,n[3][o]=h,h=16843009*l^65537*p^257*f^16843008*o,a[0][c]=h<<24|h>>>8,a[1][c]=h<<16|h>>>16,a[2][c]=h<<8|h>>>24,a[3][c]=h,0===o?o=s=1:(o=f^e[e[e[l^f]]],s^=e[e[s]])}return{SBOX:r,INV_SBOX:i,SUB_MIX:n,INV_SUB_MIX:a}}();function s(e){this._key=i(e),this._reset()}s.blockSize=16,s.keySize=32,s.prototype.blockSize=s.blockSize,s.prototype.keySize=s.keySize,s.prototype._reset=function(){for(var e=this._key,t=e.length,r=t+6,i=4*(r+1),n=[],a=0;a>>24,o=l.SBOX[o>>>24]<<24|l.SBOX[o>>>16&255]<<16|l.SBOX[o>>>8&255]<<8|l.SBOX[255&o],o^=p[a/t|0]<<24):6>>24]<<24|l.SBOX[o>>>16&255]<<16|l.SBOX[o>>>8&255]<<8|l.SBOX[255&o]),n[a]=n[a-t]^o}for(var s=[],u=0;u>>24]]^l.INV_SUB_MIX[1][l.SBOX[f>>>16&255]]^l.INV_SUB_MIX[2][l.SBOX[f>>>8&255]]^l.INV_SUB_MIX[3][l.SBOX[255&f]]}this._nRounds=r,this._keySchedule=n,this._invKeySchedule=s},s.prototype.encryptBlockRaw=function(e){return o(e=i(e),this._keySchedule,l.SUB_MIX,l.SBOX,this._nRounds)},s.prototype.encryptBlock=function(e){var t=this.encryptBlockRaw(e),e=n.allocUnsafe(16);return e.writeUInt32BE(t[0],0),e.writeUInt32BE(t[1],4),e.writeUInt32BE(t[2],8),e.writeUInt32BE(t[3],12),e},s.prototype.decryptBlock=function(e){var t=(e=i(e))[1];e[1]=e[3],e[3]=t;t=o(e,this._invKeySchedule,l.INV_SUB_MIX,l.INV_SBOX,this._nRounds),e=n.allocUnsafe(16);return e.writeUInt32BE(t[0],0),e.writeUInt32BE(t[3],4),e.writeUInt32BE(t[2],8),e.writeUInt32BE(t[1],12),e},s.prototype.scrub=function(){a(this._keySchedule),a(this._invKeySchedule),a(this._key)},t.exports.AES=s},{"safe-buffer":421}],134:[function(e,t,r){var a=e("./aes"),o=e("safe-buffer").Buffer,s=e("cipher-base"),i=e("inherits"),u=e("./ghash"),n=e("buffer-xor"),c=e("./incr32");function f(e,t,r,i){s.call(this);var n=o.alloc(4,0);this._cipher=new a.AES(t);n=this._cipher.encryptBlock(n);this._ghash=new u(n),r=function(e,t,r){if(12===t.length)return e._finID=o.concat([t,o.from([0,0,0,1])]),o.concat([t,o.from([0,0,0,2])]);var i=new u(r),n=t.length,r=n%16;return i.update(t),r&&(r=16-r,i.update(o.alloc(r,0))),i.update(o.alloc(8,0)),r=8*n,(n=o.alloc(8)).writeUIntBE(r,0,8),i.update(n),e._finID=i.state,e=o.from(e._finID),c(e),e}(this,r,n),this._prev=o.from(r),this._cache=o.allocUnsafe(0),this._secCache=o.allocUnsafe(0),this._decrypt=i,this._alen=0,this._len=0,this._mode=e,this._authTag=null,this._called=!1}i(f,s),f.prototype._update=function(e){this._called||!this._alen||(t=16-this._alen%16)<16&&(t=o.alloc(t,0),this._ghash.update(t)),this._called=!0;var t=this._mode.encrypt(this,e);return this._decrypt?this._ghash.update(e):this._ghash.update(t),this._len+=e.length,t},f.prototype._final=function(){if(this._decrypt&&!this._authTag)throw new Error("Unsupported state or unable to authenticate data");var e=n(this._ghash.final(8*this._alen,8*this._len),this._cipher.encryptBlock(this._finID));if(this._decrypt&&function(e,t){var r=0;e.length!==t.length&&r++;for(var i=Math.min(e.length,t.length),n=0;n>>0,0),t.writeUInt32BE(e[1]>>>0,4),t.writeUInt32BE(e[2]>>>0,8),t.writeUInt32BE(e[3]>>>0,12),t}function a(e){this.h=e,this.state=i.alloc(16,0),this.cache=i.allocUnsafe(0)}a.prototype.ghash=function(e){for(var t=-1;++t>>1|(1&i[t-1])<<31;i[0]=i[0]>>>1,r&&(i[0]=i[0]^225<<24)}this.state=o(n)},a.prototype.update=function(e){var t;for(this.cache=i.concat([this.cache,e]);16<=this.cache.length;)t=this.cache.slice(0,16),this.cache=this.cache.slice(16),this.ghash(t)},a.prototype.final=function(e,t){return this.cache.length&&this.ghash(i.concat([this.cache,n],16)),this.ghash(o([0,e,0,t])),this.state},t.exports=a},{"safe-buffer":421}],139:[function(e,t,r){t.exports=function(e){for(var t,r=e.length;r--;){if(255!==(t=e.readUInt8(r))){t++,e.writeUInt8(t,r);break}e.writeUInt8(0,r)}}},{}],140:[function(e,t,r){var i=e("buffer-xor");r.encrypt=function(e,t){t=i(t,e._prev);return e._prev=e._cipher.encryptBlock(t),e._prev},r.decrypt=function(e,t){var r=e._prev;e._prev=t;t=e._cipher.decryptBlock(t);return i(t,r)}},{"buffer-xor":185}],141:[function(e,t,r){var a=e("safe-buffer").Buffer,o=e("buffer-xor");function s(e,t,r){var i=t.length,n=o(t,e._cache);return e._cache=e._cache.slice(i),e._prev=a.concat([e._prev,r?t:n]),n}r.encrypt=function(e,t,r){for(var i,n=a.allocUnsafe(0);t.length;){if(0===e._cache.length&&(e._cache=e._cipher.encryptBlock(e._prev),e._prev=a.allocUnsafe(0)),!(e._cache.length<=t.length)){n=a.concat([n,s(e,t,r)]);break}i=e._cache.length,n=a.concat([n,s(e,t.slice(0,i),r)]),t=t.slice(i)}return n}},{"buffer-xor":185,"safe-buffer":421}],142:[function(e,t,r){var s=e("safe-buffer").Buffer;function o(e,t,r){for(var i,n,a=-1,o=0;++a<8;)i=t&1<<7-a?128:0,o+=(128&(n=e._cipher.encryptBlock(e._prev)[0]^i))>>a%8,e._prev=function(e,t){var r=e.length,i=-1,n=s.allocUnsafe(e.length);e=s.concat([e,s.from([t])]);for(;++i>7;return n}(e._prev,r?i:n);return o}r.encrypt=function(e,t,r){for(var i=t.length,n=s.allocUnsafe(i),a=-1;++a>>26-o&67108863,26<=(o+=24)&&(o-=26,i++);else if("le"===r)for(i=a=0;a>>26-o&67108863,26<=(o+=24)&&(o-=26,i++);return this._strip()},g.prototype._parseHex=function(e,t){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var r,i=0;i>>26-n&4194303,26<=(n+=24)&&(n-=26,a++);i+6!==t&&(r=o(e,t,i+6),this.words[a]|=r<>>26-n&4194303),this._strip()},g.prototype._parseBase=function(e,t,r){this.words=[0];for(var i=0,n=this.length=1;n<=67108863;n*=t)i++;i--,n=n/t|0;for(var a=e.length-r,o=a%i,s=Math.min(a,a-o)+r,u=0,c=r;c"}var l=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],h=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],d=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function s(e,t,r){r.negative=t.negative^e.negative;var i=e.length+t.length|0,i=(r.length=i)-1|0,n=67108863&(p=(0|e.words[0])*(0|t.words[0])),a=p/67108864|0;r.words[0]=n;for(var o=1;o>>26,u=67108863&a,c=Math.min(o,t.length-1),f=Math.max(0,o-e.length+1);f<=c;f++){var p,l=o-f|0;s+=(p=(0|e.words[l])*(0|t.words[f])+u)/67108864|0,u=67108863&p}r.words[o]=0|u,a=0|s}return 0!==a?r.words[o]=0|a:r.length--,r._strip()}g.prototype.toString=function(e,t){if(t=0|t||1,16===(e=e||10)||"hex"===e){s="";for(var r=0,i=0,n=0;n>>24-r&16777215)||n!==this.length-1?l[6-o.length]+o+s:o+s;26<=(r+=2)&&(r-=26,n--)}for(0!==i&&(s=i.toString(16)+s);s.length%t!=0;)s="0"+s;return s=0!==this.negative?"-"+s:s}if(e===(0|e)&&2<=e&&e<=36){var u=h[e],c=d[e];for(s="",(f=this.clone()).negative=0;!f.isZero();){var f,p=f.modrn(c).toString(e);s=(f=f.idivn(c)).isZero()?p+s:l[u-p.length]+p+s}for(this.isZero()&&(s="0"+s);s.length%t!=0;)s="0"+s;return s=0!==this.negative?"-"+s:s}m(!1,"Base should be between 2 and 36")},g.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:2>8&255),r>16&255),6===a?(r>24&255),a=i=0):(i=o>>>24,a+=2)}if(r>8&255),0<=r&&(e[r--]=o>>16&255),6===a?(0<=r&&(e[r--]=o>>24&255),a=i=0):(i=o>>>24,a+=2)}if(0<=r)for(e[r--]=i;0<=r;)e[r--]=0},Math.clz32?g.prototype._countBits=function(e){return 32-Math.clz32(e)}:g.prototype._countBits=function(e){var t=e,e=0;return 4096<=t&&(e+=13,t>>>=13),64<=t&&(e+=7,t>>>=7),8<=t&&(e+=4,t>>>=4),2<=t&&(e+=2,t>>>=2),e+t},g.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,e=0;return 0==(8191&t)&&(e+=13,t>>>=13),0==(127&t)&&(e+=7,t>>>=7),0==(15&t)&&(e+=4,t>>>=4),0==(3&t)&&(e+=2,t>>>=2),0==(1&t)&&e++,e},g.prototype.bitLength=function(){var e=this.words[this.length-1],e=this._countBits(e);return 26*(this.length-1)+e},g.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;te.length?this.clone().ior(e):e.clone().ior(this)},g.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},g.prototype.iuand=function(e){for(var t=this.length>e.length?e:this,r=0;re.length?this.clone().iand(e):e.clone().iand(this)},g.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},g.prototype.iuxor=function(e){for(var t,r=this.length>e.length?(t=this,e):(t=e,this),i=0;ie.length?this.clone().ixor(e):e.clone().ixor(this)},g.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},g.prototype.inotn=function(e){m("number"==typeof e&&0<=e);var t=0|Math.ceil(e/26),e=e%26;this._expand(t),0>26-e),this._strip()},g.prototype.notn=function(e){return this.clone().inotn(e)},g.prototype.setn=function(e,t){m("number"==typeof e&&0<=e);var r=e/26|0,e=e%26;return this._expand(1+r),this.words[r]=t?this.words[r]|1<e.length?(r=this,e):(r=e,this);for(var n=0,a=0;a>>26;for(;0!==n&&a>>26;if(this.length=r.length,0!==n)this.words[this.length]=n,this.length++;else if(r!==this)for(;ae.length?this.clone().iadd(e):e.clone().iadd(this)},g.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var r,i,n=this.cmp(e);if(0===n)return this.negative=0,this.length=1,this.words[0]=0,this;i=0>26,this.words[o]=67108863&t;for(;0!==a&&o>26,this.words[o]=67108863&t;if(0===a&&o>>13,c=0|i[1],f=8191&c,p=c>>>13,l=0|i[2],h=8191&l,d=l>>>13,m=0|i[3],g=8191&m,b=m>>>13,y=0|i[4],v=8191&y,_=y>>>13,w=0|i[5],k=8191&w,x=w>>>13,S=0|i[6],j=8191&S,E=S>>>13,A=0|i[7],P=8191&A,I=A>>>13,T=0|i[8],O=8191&T,C=T>>>13,R=0|i[9],B=8191&R,F=R>>>13,M=0|n[0],z=8191&M,N=M>>>13,D=0|n[1],L=8191&D,q=D>>>13,U=0|n[2],H=8191&U,K=U>>>13,V=0|n[3],$=8191&V,G=V>>>13,W=0|n[4],Z=8191&W,Y=W>>>13,Q=0|n[5],X=8191&Q,J=Q>>>13,o=0|n[6],c=8191&o,l=o>>>13,m=0|n[7],y=8191&m,w=m>>>13,S=0|n[8],A=8191&S,T=S>>>13,i=0|n[9],R=8191&i,M=i>>>13;r.negative=e.negative^t.negative,r.length=19;var V=(0+Math.imul(s,z)|0)+((8191&(U=Math.imul(s,N)+Math.imul(u,z)|0))<<13)|0,ee=(Math.imul(u,N)+(U>>>13)|0)+(V>>>26)|0;V&=67108863,D=Math.imul(f,z),U=Math.imul(f,N)+Math.imul(p,z)|0,W=Math.imul(p,N);Q=(ee+(D+Math.imul(s,L)|0)|0)+((8191&(U=(U+Math.imul(s,q)|0)+Math.imul(u,L)|0))<<13)|0;ee=((W+Math.imul(u,q)|0)+(U>>>13)|0)+(Q>>>26)|0,Q&=67108863,D=Math.imul(h,z),U=Math.imul(h,N)+Math.imul(d,z)|0,W=Math.imul(d,N),D=D+Math.imul(f,L)|0,U=(U+Math.imul(f,q)|0)+Math.imul(p,L)|0,W=W+Math.imul(p,q)|0;o=(ee+(D+Math.imul(s,H)|0)|0)+((8191&(U=(U+Math.imul(s,K)|0)+Math.imul(u,H)|0))<<13)|0;ee=((W+Math.imul(u,K)|0)+(U>>>13)|0)+(o>>>26)|0,o&=67108863,D=Math.imul(g,z),U=Math.imul(g,N)+Math.imul(b,z)|0,W=Math.imul(b,N),D=D+Math.imul(h,L)|0,U=(U+Math.imul(h,q)|0)+Math.imul(d,L)|0,W=W+Math.imul(d,q)|0,D=D+Math.imul(f,H)|0,U=(U+Math.imul(f,K)|0)+Math.imul(p,H)|0,W=W+Math.imul(p,K)|0;m=(ee+(D+Math.imul(s,$)|0)|0)+((8191&(U=(U+Math.imul(s,G)|0)+Math.imul(u,$)|0))<<13)|0;ee=((W+Math.imul(u,G)|0)+(U>>>13)|0)+(m>>>26)|0,m&=67108863,D=Math.imul(v,z),U=Math.imul(v,N)+Math.imul(_,z)|0,W=Math.imul(_,N),D=D+Math.imul(g,L)|0,U=(U+Math.imul(g,q)|0)+Math.imul(b,L)|0,W=W+Math.imul(b,q)|0,D=D+Math.imul(h,H)|0,U=(U+Math.imul(h,K)|0)+Math.imul(d,H)|0,W=W+Math.imul(d,K)|0,D=D+Math.imul(f,$)|0,U=(U+Math.imul(f,G)|0)+Math.imul(p,$)|0,W=W+Math.imul(p,G)|0;S=(ee+(D+Math.imul(s,Z)|0)|0)+((8191&(U=(U+Math.imul(s,Y)|0)+Math.imul(u,Z)|0))<<13)|0;ee=((W+Math.imul(u,Y)|0)+(U>>>13)|0)+(S>>>26)|0,S&=67108863,D=Math.imul(k,z),U=Math.imul(k,N)+Math.imul(x,z)|0,W=Math.imul(x,N),D=D+Math.imul(v,L)|0,U=(U+Math.imul(v,q)|0)+Math.imul(_,L)|0,W=W+Math.imul(_,q)|0,D=D+Math.imul(g,H)|0,U=(U+Math.imul(g,K)|0)+Math.imul(b,H)|0,W=W+Math.imul(b,K)|0,D=D+Math.imul(h,$)|0,U=(U+Math.imul(h,G)|0)+Math.imul(d,$)|0,W=W+Math.imul(d,G)|0,D=D+Math.imul(f,Z)|0,U=(U+Math.imul(f,Y)|0)+Math.imul(p,Z)|0,W=W+Math.imul(p,Y)|0;n=(ee+(D+Math.imul(s,X)|0)|0)+((8191&(U=(U+Math.imul(s,J)|0)+Math.imul(u,X)|0))<<13)|0;ee=((W+Math.imul(u,J)|0)+(U>>>13)|0)+(n>>>26)|0,n&=67108863,D=Math.imul(j,z),U=Math.imul(j,N)+Math.imul(E,z)|0,W=Math.imul(E,N),D=D+Math.imul(k,L)|0,U=(U+Math.imul(k,q)|0)+Math.imul(x,L)|0,W=W+Math.imul(x,q)|0,D=D+Math.imul(v,H)|0,U=(U+Math.imul(v,K)|0)+Math.imul(_,H)|0,W=W+Math.imul(_,K)|0,D=D+Math.imul(g,$)|0,U=(U+Math.imul(g,G)|0)+Math.imul(b,$)|0,W=W+Math.imul(b,G)|0,D=D+Math.imul(h,Z)|0,U=(U+Math.imul(h,Y)|0)+Math.imul(d,Z)|0,W=W+Math.imul(d,Y)|0,D=D+Math.imul(f,X)|0,U=(U+Math.imul(f,J)|0)+Math.imul(p,X)|0,W=W+Math.imul(p,J)|0;i=(ee+(D+Math.imul(s,c)|0)|0)+((8191&(U=(U+Math.imul(s,l)|0)+Math.imul(u,c)|0))<<13)|0;ee=((W+Math.imul(u,l)|0)+(U>>>13)|0)+(i>>>26)|0,i&=67108863,D=Math.imul(P,z),U=Math.imul(P,N)+Math.imul(I,z)|0,W=Math.imul(I,N),D=D+Math.imul(j,L)|0,U=(U+Math.imul(j,q)|0)+Math.imul(E,L)|0,W=W+Math.imul(E,q)|0,D=D+Math.imul(k,H)|0,U=(U+Math.imul(k,K)|0)+Math.imul(x,H)|0,W=W+Math.imul(x,K)|0,D=D+Math.imul(v,$)|0,U=(U+Math.imul(v,G)|0)+Math.imul(_,$)|0,W=W+Math.imul(_,G)|0,D=D+Math.imul(g,Z)|0,U=(U+Math.imul(g,Y)|0)+Math.imul(b,Z)|0,W=W+Math.imul(b,Y)|0,D=D+Math.imul(h,X)|0,U=(U+Math.imul(h,J)|0)+Math.imul(d,X)|0,W=W+Math.imul(d,J)|0,D=D+Math.imul(f,c)|0,U=(U+Math.imul(f,l)|0)+Math.imul(p,c)|0,W=W+Math.imul(p,l)|0;e=(ee+(D+Math.imul(s,y)|0)|0)+((8191&(U=(U+Math.imul(s,w)|0)+Math.imul(u,y)|0))<<13)|0;ee=((W+Math.imul(u,w)|0)+(U>>>13)|0)+(e>>>26)|0,e&=67108863,D=Math.imul(O,z),U=Math.imul(O,N)+Math.imul(C,z)|0,W=Math.imul(C,N),D=D+Math.imul(P,L)|0,U=(U+Math.imul(P,q)|0)+Math.imul(I,L)|0,W=W+Math.imul(I,q)|0,D=D+Math.imul(j,H)|0,U=(U+Math.imul(j,K)|0)+Math.imul(E,H)|0,W=W+Math.imul(E,K)|0,D=D+Math.imul(k,$)|0,U=(U+Math.imul(k,G)|0)+Math.imul(x,$)|0,W=W+Math.imul(x,G)|0,D=D+Math.imul(v,Z)|0,U=(U+Math.imul(v,Y)|0)+Math.imul(_,Z)|0,W=W+Math.imul(_,Y)|0,D=D+Math.imul(g,X)|0,U=(U+Math.imul(g,J)|0)+Math.imul(b,X)|0,W=W+Math.imul(b,J)|0,D=D+Math.imul(h,c)|0,U=(U+Math.imul(h,l)|0)+Math.imul(d,c)|0,W=W+Math.imul(d,l)|0,D=D+Math.imul(f,y)|0,U=(U+Math.imul(f,w)|0)+Math.imul(p,y)|0,W=W+Math.imul(p,w)|0;t=(ee+(D+Math.imul(s,A)|0)|0)+((8191&(U=(U+Math.imul(s,T)|0)+Math.imul(u,A)|0))<<13)|0;ee=((W+Math.imul(u,T)|0)+(U>>>13)|0)+(t>>>26)|0,t&=67108863,D=Math.imul(B,z),U=Math.imul(B,N)+Math.imul(F,z)|0,W=Math.imul(F,N),D=D+Math.imul(O,L)|0,U=(U+Math.imul(O,q)|0)+Math.imul(C,L)|0,W=W+Math.imul(C,q)|0,D=D+Math.imul(P,H)|0,U=(U+Math.imul(P,K)|0)+Math.imul(I,H)|0,W=W+Math.imul(I,K)|0,D=D+Math.imul(j,$)|0,U=(U+Math.imul(j,G)|0)+Math.imul(E,$)|0,W=W+Math.imul(E,G)|0,D=D+Math.imul(k,Z)|0,U=(U+Math.imul(k,Y)|0)+Math.imul(x,Z)|0,W=W+Math.imul(x,Y)|0,D=D+Math.imul(v,X)|0,U=(U+Math.imul(v,J)|0)+Math.imul(_,X)|0,W=W+Math.imul(_,J)|0,D=D+Math.imul(g,c)|0,U=(U+Math.imul(g,l)|0)+Math.imul(b,c)|0,W=W+Math.imul(b,l)|0,D=D+Math.imul(h,y)|0,U=(U+Math.imul(h,w)|0)+Math.imul(d,y)|0,W=W+Math.imul(d,w)|0,D=D+Math.imul(f,A)|0,U=(U+Math.imul(f,T)|0)+Math.imul(p,A)|0,W=W+Math.imul(p,T)|0;s=(ee+(D+Math.imul(s,R)|0)|0)+((8191&(U=(U+Math.imul(s,M)|0)+Math.imul(u,R)|0))<<13)|0;ee=((W+Math.imul(u,M)|0)+(U>>>13)|0)+(s>>>26)|0,s&=67108863,D=Math.imul(B,L),U=Math.imul(B,q)+Math.imul(F,L)|0,W=Math.imul(F,q),D=D+Math.imul(O,H)|0,U=(U+Math.imul(O,K)|0)+Math.imul(C,H)|0,W=W+Math.imul(C,K)|0,D=D+Math.imul(P,$)|0,U=(U+Math.imul(P,G)|0)+Math.imul(I,$)|0,W=W+Math.imul(I,G)|0,D=D+Math.imul(j,Z)|0,U=(U+Math.imul(j,Y)|0)+Math.imul(E,Z)|0,W=W+Math.imul(E,Y)|0,D=D+Math.imul(k,X)|0,U=(U+Math.imul(k,J)|0)+Math.imul(x,X)|0,W=W+Math.imul(x,J)|0,D=D+Math.imul(v,c)|0,U=(U+Math.imul(v,l)|0)+Math.imul(_,c)|0,W=W+Math.imul(_,l)|0,D=D+Math.imul(g,y)|0,U=(U+Math.imul(g,w)|0)+Math.imul(b,y)|0,W=W+Math.imul(b,w)|0,D=D+Math.imul(h,A)|0,U=(U+Math.imul(h,T)|0)+Math.imul(d,A)|0,W=W+Math.imul(d,T)|0;f=(ee+(D+Math.imul(f,R)|0)|0)+((8191&(U=(U+Math.imul(f,M)|0)+Math.imul(p,R)|0))<<13)|0;ee=((W+Math.imul(p,M)|0)+(U>>>13)|0)+(f>>>26)|0,f&=67108863,D=Math.imul(B,H),U=Math.imul(B,K)+Math.imul(F,H)|0,W=Math.imul(F,K),D=D+Math.imul(O,$)|0,U=(U+Math.imul(O,G)|0)+Math.imul(C,$)|0,W=W+Math.imul(C,G)|0,D=D+Math.imul(P,Z)|0,U=(U+Math.imul(P,Y)|0)+Math.imul(I,Z)|0,W=W+Math.imul(I,Y)|0,D=D+Math.imul(j,X)|0,U=(U+Math.imul(j,J)|0)+Math.imul(E,X)|0,W=W+Math.imul(E,J)|0,D=D+Math.imul(k,c)|0,U=(U+Math.imul(k,l)|0)+Math.imul(x,c)|0,W=W+Math.imul(x,l)|0,D=D+Math.imul(v,y)|0,U=(U+Math.imul(v,w)|0)+Math.imul(_,y)|0,W=W+Math.imul(_,w)|0,D=D+Math.imul(g,A)|0,U=(U+Math.imul(g,T)|0)+Math.imul(b,A)|0,W=W+Math.imul(b,T)|0;h=(ee+(D+Math.imul(h,R)|0)|0)+((8191&(U=(U+Math.imul(h,M)|0)+Math.imul(d,R)|0))<<13)|0;ee=((W+Math.imul(d,M)|0)+(U>>>13)|0)+(h>>>26)|0,h&=67108863,D=Math.imul(B,$),U=Math.imul(B,G)+Math.imul(F,$)|0,W=Math.imul(F,G),D=D+Math.imul(O,Z)|0,U=(U+Math.imul(O,Y)|0)+Math.imul(C,Z)|0,W=W+Math.imul(C,Y)|0,D=D+Math.imul(P,X)|0,U=(U+Math.imul(P,J)|0)+Math.imul(I,X)|0,W=W+Math.imul(I,J)|0,D=D+Math.imul(j,c)|0,U=(U+Math.imul(j,l)|0)+Math.imul(E,c)|0,W=W+Math.imul(E,l)|0,D=D+Math.imul(k,y)|0,U=(U+Math.imul(k,w)|0)+Math.imul(x,y)|0,W=W+Math.imul(x,w)|0,D=D+Math.imul(v,A)|0,U=(U+Math.imul(v,T)|0)+Math.imul(_,A)|0,W=W+Math.imul(_,T)|0;g=(ee+(D+Math.imul(g,R)|0)|0)+((8191&(U=(U+Math.imul(g,M)|0)+Math.imul(b,R)|0))<<13)|0;ee=((W+Math.imul(b,M)|0)+(U>>>13)|0)+(g>>>26)|0,g&=67108863,D=Math.imul(B,Z),U=Math.imul(B,Y)+Math.imul(F,Z)|0,W=Math.imul(F,Y),D=D+Math.imul(O,X)|0,U=(U+Math.imul(O,J)|0)+Math.imul(C,X)|0,W=W+Math.imul(C,J)|0,D=D+Math.imul(P,c)|0,U=(U+Math.imul(P,l)|0)+Math.imul(I,c)|0,W=W+Math.imul(I,l)|0,D=D+Math.imul(j,y)|0,U=(U+Math.imul(j,w)|0)+Math.imul(E,y)|0,W=W+Math.imul(E,w)|0,D=D+Math.imul(k,A)|0,U=(U+Math.imul(k,T)|0)+Math.imul(x,A)|0,W=W+Math.imul(x,T)|0;v=(ee+(D+Math.imul(v,R)|0)|0)+((8191&(U=(U+Math.imul(v,M)|0)+Math.imul(_,R)|0))<<13)|0;ee=((W+Math.imul(_,M)|0)+(U>>>13)|0)+(v>>>26)|0,v&=67108863,D=Math.imul(B,X),U=Math.imul(B,J)+Math.imul(F,X)|0,W=Math.imul(F,J),D=D+Math.imul(O,c)|0,U=(U+Math.imul(O,l)|0)+Math.imul(C,c)|0,W=W+Math.imul(C,l)|0,D=D+Math.imul(P,y)|0,U=(U+Math.imul(P,w)|0)+Math.imul(I,y)|0,W=W+Math.imul(I,w)|0,D=D+Math.imul(j,A)|0,U=(U+Math.imul(j,T)|0)+Math.imul(E,A)|0,W=W+Math.imul(E,T)|0;k=(ee+(D+Math.imul(k,R)|0)|0)+((8191&(U=(U+Math.imul(k,M)|0)+Math.imul(x,R)|0))<<13)|0;ee=((W+Math.imul(x,M)|0)+(U>>>13)|0)+(k>>>26)|0,k&=67108863,D=Math.imul(B,c),U=Math.imul(B,l)+Math.imul(F,c)|0,W=Math.imul(F,l),D=D+Math.imul(O,y)|0,U=(U+Math.imul(O,w)|0)+Math.imul(C,y)|0,W=W+Math.imul(C,w)|0,D=D+Math.imul(P,A)|0,U=(U+Math.imul(P,T)|0)+Math.imul(I,A)|0,W=W+Math.imul(I,T)|0;j=(ee+(D+Math.imul(j,R)|0)|0)+((8191&(U=(U+Math.imul(j,M)|0)+Math.imul(E,R)|0))<<13)|0;ee=((W+Math.imul(E,M)|0)+(U>>>13)|0)+(j>>>26)|0,j&=67108863,D=Math.imul(B,y),U=Math.imul(B,w)+Math.imul(F,y)|0,W=Math.imul(F,w),D=D+Math.imul(O,A)|0,U=(U+Math.imul(O,T)|0)+Math.imul(C,A)|0,W=W+Math.imul(C,T)|0;P=(ee+(D+Math.imul(P,R)|0)|0)+((8191&(U=(U+Math.imul(P,M)|0)+Math.imul(I,R)|0))<<13)|0;ee=((W+Math.imul(I,M)|0)+(U>>>13)|0)+(P>>>26)|0,P&=67108863,D=Math.imul(B,A),U=Math.imul(B,T)+Math.imul(F,A)|0,W=Math.imul(F,T);O=(ee+(D+Math.imul(O,R)|0)|0)+((8191&(U=(U+Math.imul(O,M)|0)+Math.imul(C,R)|0))<<13)|0;ee=((W+Math.imul(C,M)|0)+(U>>>13)|0)+(O>>>26)|0,O&=67108863;R=(ee+Math.imul(B,R)|0)+((8191&(U=Math.imul(B,M)+Math.imul(F,R)|0))<<13)|0;return ee=(Math.imul(F,M)+(U>>>13)|0)+(R>>>26)|0,R&=67108863,a[0]=V,a[1]=Q,a[2]=o,a[3]=m,a[4]=S,a[5]=n,a[6]=i,a[7]=e,a[8]=t,a[9]=s,a[10]=f,a[11]=h,a[12]=g,a[13]=v,a[14]=k,a[15]=j,a[16]=P,a[17]=O,a[18]=R,0!=ee&&(a[19]=ee,r.length++),r};function c(e,t,r){r.negative=t.negative^e.negative,r.length=e.length+t.length;for(var i=0,n=0,a=0;a>>26)|0)>>>26,o&=67108863}r.words[a]=s,i=o,o=n}return 0!==i?r.words[a]=i:r.length--,r._strip()}function f(e,t,r){return c(e,t,r)}Math.imul||(u=s),g.prototype.mulTo=function(e,t){var r=this.length+e.length,t=(10===this.length&&10===e.length?u:r<63?s:r<1024?c:f)(this,e,t);return t},g.prototype.mul=function(e){var t=new g(null);return t.words=new Array(this.length+e.length),this.mulTo(e,t)},g.prototype.mulf=function(e){var t=new g(null);return t.words=new Array(this.length+e.length),f(this,e,t)},g.prototype.imul=function(e){return this.clone().mulTo(e,this)},g.prototype.imuln=function(e){var t=e<0;m("number"==typeof(e=t?-e:e)),m(e<67108864);for(var r=0,i=0;i>=26,r+=n/67108864|0,r+=a>>>26,this.words[i]=67108863&a}return 0!==r&&(this.words[i]=r,this.length++),t?this.ineg():this},g.prototype.muln=function(e){return this.clone().imuln(e)},g.prototype.sqr=function(){return this.mul(this)},g.prototype.isqr=function(){return this.imul(this.clone())},g.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),r=0;r>>n&1}return t}(e);if(0===t.length)return new g(1);for(var r=this,i=0;i>>26-t<<26-t;if(0!=t){for(var n=0,a=0;a>>26-t}n&&(this.words[a]=n,this.length++)}if(0!=r){for(a=this.length-1;0<=a;a--)this.words[a+r]=this.words[a];for(a=0;a>>n<a)for(this.length-=a,u=0;u>>n,c=f&o}return s&&0!==c&&(s.words[s.length++]=c),0===this.length&&(this.words[0]=0,this.length=1),this._strip()},g.prototype.ishrn=function(e,t,r){return m(0===this.negative),this.iushrn(e,t,r)},g.prototype.shln=function(e){return this.clone().ishln(e)},g.prototype.ushln=function(e){return this.clone().iushln(e)},g.prototype.shrn=function(e){return this.clone().ishrn(e)},g.prototype.ushrn=function(e){return this.clone().iushrn(e)},g.prototype.testn=function(e){m("number"==typeof e&&0<=e);var t=e%26,e=(e-t)/26,t=1<>>t<>26)-(s/67108864|0);this.words[o+r]=67108863&i}for(;o>26,this.words[o+r]=67108863&i;if(0===a)return this._strip();for(m(-1===a),o=a=0;o>26,this.words[o]=67108863&i;return this.negative=1,this._strip()},g.prototype._wordDiv=function(e,t){var r=this.length-e.length,i=this.clone(),n=e,a=0|n.words[n.length-1];0!=(r=26-this._countBits(a))&&(n=n.ushln(r),i.iushln(r),a=0|n.words[n.length-1]);var o,s=i.length-n.length;if("mod"!==t){(o=new g(null)).length=1+s,o.words=new Array(o.length);for(var u=0;uthis.length||this.cmp(e)<0?{div:new g(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new g(this.modrn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new g(this.modrn(e.words[0]))}:this._wordDiv(e,t);var i,n,a},g.prototype.div=function(e){return this.divmod(e,"div",!1).div},g.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},g.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},g.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var r=0!==t.div.negative?t.mod.isub(e):t.mod,i=e.ushrn(1),e=e.andln(1),i=r.cmp(i);return i<0||1===e&&0===i?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},g.prototype.modrn=function(e){var t=e<0;m((e=t?-e:e)<=67108863);for(var r=(1<<26)%e,i=0,n=this.length-1;0<=n;n--)i=(r*i+(0|this.words[n]))%e;return t?-i:i},g.prototype.modn=function(e){return this.modrn(e)},g.prototype.idivn=function(e){var t=e<0;m((e=t?-e:e)<=67108863);for(var r=0,i=this.length-1;0<=i;i--){var n=(0|this.words[i])+67108864*r;this.words[i]=n/e|0,r=n%e}return this._strip(),t?this.ineg():this},g.prototype.divn=function(e){return this.clone().idivn(e)},g.prototype.egcd=function(e){m(0===e.negative),m(!e.isZero());for(var t=this,r=e.clone(),t=0!==t.negative?t.umod(e):t.clone(),i=new g(1),n=new g(0),a=new g(0),o=new g(1),s=0;t.isEven()&&r.isEven();)t.iushrn(1),r.iushrn(1),++s;for(var u=r.clone(),c=t.clone();!t.isZero();){for(var f=0,p=1;0==(t.words[0]&p)&&f<26;++f,p<<=1);if(0>>26;n&=67108863,this.words[i]=n}return 0!==r&&(this.words[i]=r,this.length++),this},g.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},g.prototype.cmpn=function(e){var t=e<0;return 0===this.negative||t?0===this.negative&&t?1:(this._strip(),e=1e.length)return 1;if(this.lengththis.n;);e=t>>22,n=a}n>>>=22,0===(e.words[i-10]=n)&&10>>=26,e.words[r]=n,t=i}return 0!==t&&(e.words[e.length++]=t),e},g._prime=function(e){if(b[e])return b[e];var t;if("k256"===e)t=new v;else if("p224"===e)t=new _;else if("p192"===e)t=new w;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new k}return b[e]=t},x.prototype._verify1=function(e){m(0===e.negative,"red works only with positives"),m(e.red,"red works only with red numbers")},x.prototype._verify2=function(e,t){m(0==(e.negative|t.negative),"red works only with positives"),m(e.red&&e.red===t.red,"red works only with red numbers")},x.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):(n(e,e.umod(this.m)._forceRed(this)),e)},x.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},x.prototype.add=function(e,t){this._verify2(e,t);t=e.add(t);return 0<=t.cmp(this.m)&&t.isub(this.m),t._forceRed(this)},x.prototype.iadd=function(e,t){this._verify2(e,t);t=e.iadd(t);return 0<=t.cmp(this.m)&&t.isub(this.m),t},x.prototype.sub=function(e,t){this._verify2(e,t);t=e.sub(t);return t.cmpn(0)<0&&t.iadd(this.m),t._forceRed(this)},x.prototype.isub=function(e,t){this._verify2(e,t);t=e.isub(t);return t.cmpn(0)<0&&t.iadd(this.m),t},x.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},x.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},x.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},x.prototype.isqr=function(e){return this.imul(e,e.clone())},x.prototype.sqr=function(e){return this.mul(e,e)},x.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(m(t%2==1),3===t){t=this.m.add(new g(1)).iushrn(2);return this.pow(e,t)}for(var r=this.m.subn(1),i=0;!r.isZero()&&0===r.andln(1);)i++,r.iushrn(1);m(!r.isZero());for(var n=new g(1).toRed(this),a=n.redNeg(),o=this.m.subn(1).iushrn(1),s=new g(2*(s=this.m.bitLength())*s).toRed(this);0!==this.pow(s,o).cmp(a);)s.redIAdd(a);for(var u=this.pow(s,r),c=this.pow(e,r.addn(1).iushrn(1)),f=this.pow(e,r),p=i;0!==f.cmp(n);){for(var l=f,h=0;0!==l.cmp(n);h++)l=l.redSqr();m(h>c&1;n!==r[0]&&(n=this.sqr(n)),0!=f||0!==a?(a<<=1,a|=f,(4===++o||0===i&&0===c)&&(n=this.mul(n,r[a]),a=o=0)):o=0}s=26}return n},x.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},x.prototype.convertFrom=function(e){e=e.clone();return e.red=null,e},g.mont=function(e){return new S(e)},r(S,x),S.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},S.prototype.convertFrom=function(e){e=this.imod(e.mul(this.rinv));return e.red=null,e},S.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;e=e.imul(t),t=e.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),e=e.isub(t).iushrn(this.shift),t=e;return 0<=e.cmp(this.m)?t=e.isub(this.m):e.cmpn(0)<0&&(t=e.iadd(this.m)),t._forceRed(this)},S.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new g(0)._forceRed(this);e=e.mul(t),t=e.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),e=e.isub(t).iushrn(this.shift),t=e;return 0<=e.cmp(this.m)?t=e.isub(this.m):e.cmpn(0)<0&&(t=e.iadd(this.m)),t._forceRed(this)},S.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(void 0===e||e,this)},{buffer:132}],155:[function(e,t,r){t.exports=e("./browser/algorithms.json")},{"./browser/algorithms.json":156}],156:[function(e,t,r){t.exports={sha224WithRSAEncryption:{sign:"rsa",hash:"sha224",id:"302d300d06096086480165030402040500041c"},"RSA-SHA224":{sign:"ecdsa/rsa",hash:"sha224",id:"302d300d06096086480165030402040500041c"},sha256WithRSAEncryption:{sign:"rsa",hash:"sha256",id:"3031300d060960864801650304020105000420"},"RSA-SHA256":{sign:"ecdsa/rsa",hash:"sha256",id:"3031300d060960864801650304020105000420"},sha384WithRSAEncryption:{sign:"rsa",hash:"sha384",id:"3041300d060960864801650304020205000430"},"RSA-SHA384":{sign:"ecdsa/rsa",hash:"sha384",id:"3041300d060960864801650304020205000430"},sha512WithRSAEncryption:{sign:"rsa",hash:"sha512",id:"3051300d060960864801650304020305000440"},"RSA-SHA512":{sign:"ecdsa/rsa",hash:"sha512",id:"3051300d060960864801650304020305000440"},"RSA-SHA1":{sign:"rsa",hash:"sha1",id:"3021300906052b0e03021a05000414"},"ecdsa-with-SHA1":{sign:"ecdsa",hash:"sha1",id:""},sha256:{sign:"ecdsa",hash:"sha256",id:""},sha224:{sign:"ecdsa",hash:"sha224",id:""},sha384:{sign:"ecdsa",hash:"sha384",id:""},sha512:{sign:"ecdsa",hash:"sha512",id:""},"DSA-SHA":{sign:"dsa",hash:"sha1",id:""},"DSA-SHA1":{sign:"dsa",hash:"sha1",id:""},DSA:{sign:"dsa",hash:"sha1",id:""},"DSA-WITH-SHA224":{sign:"dsa",hash:"sha224",id:""},"DSA-SHA224":{sign:"dsa",hash:"sha224",id:""},"DSA-WITH-SHA256":{sign:"dsa",hash:"sha256",id:""},"DSA-SHA256":{sign:"dsa",hash:"sha256",id:""},"DSA-WITH-SHA384":{sign:"dsa",hash:"sha384",id:""},"DSA-SHA384":{sign:"dsa",hash:"sha384",id:""},"DSA-WITH-SHA512":{sign:"dsa",hash:"sha512",id:""},"DSA-SHA512":{sign:"dsa",hash:"sha512",id:""},"DSA-RIPEMD160":{sign:"dsa",hash:"rmd160",id:""},ripemd160WithRSA:{sign:"rsa",hash:"rmd160",id:"3021300906052b2403020105000414"},"RSA-RIPEMD160":{sign:"rsa",hash:"rmd160",id:"3021300906052b2403020105000414"},md5WithRSAEncryption:{sign:"rsa",hash:"md5",id:"3020300c06082a864886f70d020505000410"},"RSA-MD5":{sign:"rsa",hash:"md5",id:"3020300c06082a864886f70d020505000410"}}},{}],157:[function(e,t,r){t.exports={"1.3.132.0.10":"secp256k1","1.3.132.0.33":"p224","1.2.840.10045.3.1.1":"p192","1.2.840.10045.3.1.7":"p256","1.3.132.0.34":"p384","1.3.132.0.35":"p521"}},{}],158:[function(e,t,r){var i=e("safe-buffer").Buffer,n=e("create-hash"),a=e("readable-stream"),o=e("inherits"),s=e("./sign"),u=e("./verify"),c=e("./algorithms.json");function f(e){a.Writable.call(this);e=c[e];if(!e)throw new Error("Unknown message digest");this._hashType=e.hash,this._hash=n(e.hash),this._tag=e.id,this._signType=e.sign}function p(e){a.Writable.call(this);e=c[e];if(!e)throw new Error("Unknown message digest");this._hash=n(e.hash),this._tag=e.id,this._signType=e.sign}function l(e){return new f(e)}function h(e){return new p(e)}Object.keys(c).forEach(function(e){c[e].id=i.from(c[e].id,"hex"),c[e.toLowerCase()]=c[e]}),o(f,a.Writable),f.prototype._write=function(e,t,r){this._hash.update(e),r()},f.prototype.update=function(e,t){return"string"==typeof e&&(e=i.from(e,t)),this._hash.update(e),this},f.prototype.sign=function(e,t){this.end();var r=this._hash.digest(),e=s(r,e,this._hashType,this._signType,this._tag);return t?e.toString(t):e},o(p,a.Writable),p.prototype._write=function(e,t,r){this._hash.update(e),r()},p.prototype.update=function(e,t){return"string"==typeof e&&(e=i.from(e,t)),this._hash.update(e),this},p.prototype.verify=function(e,t,r){"string"==typeof t&&(t=i.from(t,r)),this.end();r=this._hash.digest();return u(t,r,e,this._signType,this._tag)},t.exports={Sign:l,Verify:h,createSign:l,createVerify:h}},{"./algorithms.json":156,"./sign":159,"./verify":160,"create-hash":194,inherits:162,"readable-stream":177,"safe-buffer":421}],159:[function(e,t,r){var l=e("safe-buffer").Buffer,a=e("create-hmac"),u=e("browserify-rsa"),c=e("elliptic").ec,h=e("bn.js"),f=e("parse-asn1"),p=e("./curves.json");function d(e,t,r,i){(e=l.from(e.toArray())).length=t)throw new Error("invalid sig")}t.exports=function(e,t,r,i,n){if("ec"===(r=h(r)).type){if("ecdsa"!==i&&"ecdsa/rsa"!==i)throw new Error("wrong public key type");return function(e,t,r){var i=d[r.data.algorithm.curve.join(".")];if(!i)throw new Error("unknown curve "+r.data.algorithm.curve.join("."));i=new l(i),r=r.data.subjectPrivateKey.data;return i.verify(t,e,r)}(e,t,r)}if("dsa"===r.type){if("dsa"!==i)throw new Error("wrong public key type");return function(e,t,r){var i=r.data.p,n=r.data.q,a=r.data.g,o=r.data.pub_key,s=h.signature.decode(e,"der"),r=s.s,e=s.r;m(r,n),m(e,n);s=p.mont(i),r=r.invm(n);return 0===a.toRed(s).redPow(new p(t).mul(r).mod(n)).fromRed().mul(o.toRed(s).redPow(e.mul(r).mod(n)).fromRed()).mod(i).mod(n).cmp(e)}(e,t,r)}if("rsa"!==i&&"ecdsa/rsa"!==i)throw new Error("wrong public key type");t=f.concat([n,t]);for(var a=r.modulus.byteLength(),o=[1],s=0;t.length+o.length+2a.length)&&(s=a.length),t=a.substring(s-o.length,s)===o?"The ".concat(e," ").concat(i," ").concat(u(t,"type")):(n=((n="number"!=typeof n?0:n)+(s=".").length>(o=e).length?void 0:-1!==o.indexOf(s,n))?"property":"argument",'The "'.concat(e,'" ').concat(n," ").concat(i," ").concat(u(t,"type"))),t+=". Received type ".concat(_typeof(r))},TypeError),n("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF"),n("ERR_METHOD_NOT_IMPLEMENTED",function(e){return"The "+e+" method is not implemented"}),n("ERR_STREAM_PREMATURE_CLOSE","Premature close"),n("ERR_STREAM_DESTROYED",function(e){return"Cannot call "+e+" after a stream was destroyed"}),n("ERR_MULTIPLE_CALLBACK","Callback called multiple times"),n("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable"),n("ERR_STREAM_WRITE_AFTER_END","write after end"),n("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),n("ERR_UNKNOWN_ENCODING",function(e){return"Unknown encoding: "+e},TypeError),n("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event"),t.exports.codes=i},{}],164:[function(f,p,e){(function(c){(function(){"use strict";var e=Object.keys||function(e){var t,r=[];for(t in e)r.push(t);return r};p.exports=o;var t=f("./_stream_readable"),r=f("./_stream_writable");f("inherits")(o,t);for(var i=e(r.prototype),n=0;nt.highWaterMark&&(t.highWaterMark=(x<=(r=e)?r=x:(r--,r|=r>>>1,r|=r>>>2,r|=r>>>4,r|=r>>>8,r|=r>>>16,r++),r)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0));var r}function j(e){var t=e._readableState;b("emitReadable",t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(b("emitReadable",t.flowing),t.emittedReadable=!0,z.nextTick(E,e))}function E(e){var t=e._readableState;b("emitReadable_",t.destroyed,t.length,t.ended),t.destroyed||!t.length&&!t.ended||(e.emit("readable"),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,C(e)}function A(e,t){t.readingMore||(t.readingMore=!0,z.nextTick(P,e,t))}function P(e,t){for(;!t.reading&&!t.ended&&(t.length=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.first():t.buffer.concat(t.length),t.buffer.clear()):r=t.buffer.consume(e,t.decoder),r);var r}function B(e){var t=e._readableState;b("endReadable",t.endEmitted),t.endEmitted||(t.ended=!0,z.nextTick(F,t,e))}function F(e,t){b("endReadableNT",e.endEmitted,e.length),e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"),!e.autoDestroy||(!(e=t._writableState)||e.autoDestroy&&e.finished)&&t.destroy())}function M(e,t){for(var r=0,i=e.length;r=t.highWaterMark:0>>0),a=this.head,o=0;a;)t=a.data,r=n,i=o,s.prototype.copy.call(t,r,i),o+=a.data.length,a=a.next;return n}},{key:"consume",value:function(e,t){var r;return en.length?n.length:e;if(a===n.length?i+=n:i+=n.slice(0,e),0===(e-=a)){a===n.length?(++r,t.next?this.head=t.next:this.head=this.tail=null):(this.head=t).data=n.slice(a);break}++r}return this.length-=r,i}},{key:"_getBuffer",value:function(e){var t=s.allocUnsafe(e),r=this.head,i=1;for(r.data.copy(t),e-=r.data.length;r=r.next;){var n=r.data,a=e>n.length?n.length:e;if(n.copy(t,t.length-e,0,a),0===(e-=a)){a===n.length?(++i,r.next?this.head=r.next:this.head=this.tail=null):(this.head=r).data=n.slice(a);break}++i}return this.length-=i,t}},{key:c,value:function(e,t){return u(this,n({},t,{depth:0,customInspect:!1}))}}])&&o(e.prototype,r),i&&o(e,i),t}()},{buffer:186,util:132}],171:[function(e,t,r){(function(u){(function(){"use strict";function a(e,t){s(e,t),o(e)}function o(e){e._writableState&&!e._writableState.emitClose||e._readableState&&!e._readableState.emitClose||e.emit("close")}function s(e,t){e.emit("error",t)}t.exports={destroy:function(e,t){var r=this,i=this._readableState&&this._readableState.destroyed,n=this._writableState&&this._writableState.destroyed;return i||n?t?t(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,u.nextTick(s,this,e)):u.nextTick(s,this,e)):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?r._writableState?r._writableState.errorEmitted?u.nextTick(o,r):(r._writableState.errorEmitted=!0,u.nextTick(a,r,e)):u.nextTick(a,r,e):t?(u.nextTick(o,r),t(e)):u.nextTick(o,r)})),this},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)},errorOrDestroy:function(e,t){var r=e._readableState,i=e._writableState;r&&r.autoDestroy||i&&i.autoDestroy?e.destroy(t):e.emit("error",t)}}}).call(this)}).call(this,e("_process"))},{_process:354}],172:[function(e,t,r){"use strict";var b=e("../../../errors").codes.ERR_STREAM_PREMATURE_CLOSE;function y(){}t.exports=function e(t,r,i){if("function"==typeof r)return e(t,null,r);var n,a;n=i||y,a=!1,i=function(){if(!a){a=!0;for(var e=arguments.length,t=new Array(e),r=0;rd.UNZIP)throw new TypeError("Bad argument");this.mode=e,this.init_done=!1,this.write_in_progress=!1,this.pending_close=!1,this.windowBits=0,this.level=0,this.memLevel=0,this.strategy=0,this.dictionary=null}function p(e,t){for(var r=0;rb.Z_MAX_CHUNK))throw new Error("Invalid chunk size: "+e.chunkSize);if(e.windowBits&&(e.windowBitsb.Z_MAX_WINDOWBITS))throw new Error("Invalid windowBits: "+e.windowBits);if(e.level&&(e.levelb.Z_MAX_LEVEL))throw new Error("Invalid compression level: "+e.level);if(e.memLevel&&(e.memLevelb.Z_MAX_MEMLEVEL))throw new Error("Invalid memLevel: "+e.memLevel);if(e.strategy&&e.strategy!=b.Z_FILTERED&&e.strategy!=b.Z_HUFFMAN_ONLY&&e.strategy!=b.Z_RLE&&e.strategy!=b.Z_FIXED&&e.strategy!=b.Z_DEFAULT_STRATEGY)throw new Error("Invalid strategy: "+e.strategy);if(e.dictionary&&!g.isBuffer(e.dictionary))throw new Error("Invalid dictionary: it should be a Buffer instance");this._binding=new o.Zlib(t);var r=this;this._hadError=!1,this._binding.onerror=function(e,t){r._binding=null,r._hadError=!0;e=new Error(e);e.errno=t,e.code=b.codes[t],r.emit("error",e)};var i=b.Z_DEFAULT_COMPRESSION;"number"==typeof e.level&&(i=e.level);t=b.Z_DEFAULT_STRATEGY;"number"==typeof e.strategy&&(t=e.strategy),this._binding.init(e.windowBits||b.Z_DEFAULT_WINDOWBITS,i,e.memLevel||b.Z_DEFAULT_MEMLEVEL,t,e.dictionary),this._buffer=new g(this._chunkSize),this._offset=0,this._closed=!1,this._level=i,this._strategy=t,this.once("end",this.close)}o.Z_MIN_WINDOWBITS=8,o.Z_MAX_WINDOWBITS=15,o.Z_DEFAULT_WINDOWBITS=15,o.Z_MIN_CHUNK=64,o.Z_MAX_CHUNK=1/0,o.Z_DEFAULT_CHUNK=16384,o.Z_MIN_MEMLEVEL=1,o.Z_MAX_MEMLEVEL=9,o.Z_DEFAULT_MEMLEVEL=8,o.Z_MIN_LEVEL=-1,o.Z_MAX_LEVEL=9,o.Z_DEFAULT_LEVEL=o.Z_DEFAULT_COMPRESSION,Object.keys(o).forEach(function(e){e.match(/^Z/)&&(b[e]=o[e])}),b.codes={Z_OK:o.Z_OK,Z_STREAM_END:o.Z_STREAM_END,Z_NEED_DICT:o.Z_NEED_DICT,Z_ERRNO:o.Z_ERRNO,Z_STREAM_ERROR:o.Z_STREAM_ERROR,Z_DATA_ERROR:o.Z_DATA_ERROR,Z_MEM_ERROR:o.Z_MEM_ERROR,Z_BUF_ERROR:o.Z_BUF_ERROR,Z_VERSION_ERROR:o.Z_VERSION_ERROR},Object.keys(b.codes).forEach(function(e){b.codes[b.codes[e]]=e}),b.Deflate=a,b.Inflate=s,b.Gzip=u,b.Gunzip=c,b.DeflateRaw=f,b.InflateRaw=p,b.Unzip=l,b.createDeflate=function(e){return new a(e)},b.createInflate=function(e){return new s(e)},b.createDeflateRaw=function(e){return new f(e)},b.createInflateRaw=function(e){return new p(e)},b.createGzip=function(e){return new u(e)},b.createGunzip=function(e){return new c(e)},b.createUnzip=function(e){return new l(e)},b.deflate=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new a(t),e,r)},b.deflateSync=function(e,t){return r(new a(t),e)},b.gzip=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new u(t),e,r)},b.gzipSync=function(e,t){return r(new u(t),e)},b.deflateRaw=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new f(t),e,r)},b.deflateRawSync=function(e,t){return r(new f(t),e)},b.unzip=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new l(t),e,r)},b.unzipSync=function(e,t){return r(new l(t),e)},b.inflate=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new s(t),e,r)},b.inflateSync=function(e,t){return r(new s(t),e)},b.gunzip=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new c(t),e,r)},b.gunzipSync=function(e,t){return r(new c(t),e)},b.inflateRaw=function(e,t,r){return"function"==typeof t&&(r=t,t={}),i(new p(t),e,r)},b.inflateRawSync=function(e,t){return r(new p(t),e)},e.inherits(t,n),t.prototype.params=function(e,t,r){if(eb.Z_MAX_LEVEL)throw new RangeError("Invalid compression level: "+e);if(t!=b.Z_FILTERED&&t!=b.Z_HUFFMAN_ONLY&&t!=b.Z_RLE&&t!=b.Z_FIXED&&t!=b.Z_DEFAULT_STRATEGY)throw new TypeError("Invalid strategy: "+t);var i;this._level!==e||this._strategy!==t?(i=this).flush(o.Z_SYNC_FLUSH,function(){i._binding.params(e,t),i._hadError||(i._level=e,i._strategy=t,r&&r())}):h.nextTick(r)},t.prototype.reset=function(){return this._binding.reset()},t.prototype._flush=function(e){this._transform(new g(0),"",e)},t.prototype.flush=function(e,t){var r,i=this._writableState;"function"!=typeof e&&(void 0!==e||t)||(t=e,e=o.Z_FULL_FLUSH),i.ended?t&&h.nextTick(t):i.ending?t&&this.once("end",t):i.needDrain?(r=this).once("drain",function(){r.flush(t)}):(this._flushFlag=e,this.write(new g(0),"",t))},t.prototype.close=function(e){var t;e&&h.nextTick(e),this._closed||(this._closed=!0,this._binding.close(),t=this,h.nextTick(function(){t.emit("close")}))},t.prototype._transform=function(e,t,r){var i,n=this._writableState,a=(n.ending||n.ended)&&(!e||n.length===e.length);if(null===!e&&!g.isBuffer(e))return r(new Error("invalid input"));a?i=o.Z_FINISH:(i=this._flushFlag,e.length>=n.length&&(this._flushFlag=this._opts.flush||o.Z_NO_FLUSH));this._processChunk(e,i,r)},t.prototype._processChunk=function(n,a,o){var s=n&&n.length,u=this._chunkSize-this._offset,c=0,f=this,p="function"==typeof o;if(!p){var t,l=[],h=0;this.on("error",function(e){t=e});do{var e=this._binding.writeSync(a,n,c,s,this._buffer,this._offset,u)}while(!this._hadError&&d(e[0],e[1]));if(this._hadError)throw t;var r=g.concat(l,h);return this.close(),r}r=this._binding.write(a,n,c,s,this._buffer,this._offset,u);function d(e,t){if(!f._hadError){var r,i=u-t;if(m(0<=i,"have should not go down"),0=f._chunkSize)&&(u=f._chunkSize,f._offset=0,f._buffer=new g(f._chunkSize)),0===t){if(c+=s-e,s=e,!p)return!0;e=f._binding.write(a,n,c,s,f._buffer,f._offset,f._chunkSize);return e.callback=d,void(e.buffer=n)}if(!p)return!1;o()}}r.buffer=n,r.callback=d},e.inherits(a,t),e.inherits(s,t),e.inherits(u,t),e.inherits(c,t),e.inherits(f,t),e.inherits(p,t),e.inherits(l,t)}).call(this)}).call(this,d("_process"),d("buffer").Buffer)},{"./binding":178,_process:354,_stream_transform:401,assert:68,buffer:186,util:481}],180:[function(e,t,r){arguments[4][132][0].apply(r,arguments)},{dup:132}],181:[function(e,C,R){(function(O){(function(){!function(e){var t="object"==_typeof(R)&&R&&!R.nodeType&&R,r="object"==_typeof(C)&&C&&!C.nodeType&&C,i="object"==_typeof(O)&&O;i.global!==i&&i.window!==i&&i.self!==i||(e=i);var n,a,b=2147483647,y=36,v=1,_=26,o=38,s=700,w=72,k=128,x="-",u=/^xn--/,c=/[^\x20-\x7E]/,f=/[\x2E\u3002\uFF0E\uFF61]/g,p={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},l=y-v,S=Math.floor,j=String.fromCharCode;function E(e){throw new RangeError(p[e])}function h(e,t){for(var r=e.length,i=[];r--;)i[r]=t(e[r]);return i}function d(e,t){var r=e.split("@"),i="";return 1>>10&1023|55296),e=56320|1023&e),t+=j(e)}).join("")}function P(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function I(e,t,r){var i=0;for(e=r?S(e/s):e>>1,e+=S(e/t);l*_>>1S((b-f)/a))&&E("overflow"),f+=s*a,!(s<(s=o<=l?v:l+_<=o?_:o-l));o+=y)a>S(b/(s=y-s))&&E("overflow"),a*=s;l=I(f-n,t=u.length+1,0==n),S(f/t)>b-p&&E("overflow"),p+=S(f/t),f%=t,u.splice(f++,0,p)}return m(u)}function T(e){for(var t,r,i,n,a,o,s,u,c,f,p,l=[],h=(e=A(e)).length,d=k,m=w,g=t=0;gS((b-t)/(c=r+1))&&E("overflow"),t+=(n-d)*c,d=n,g=0;gb&&E("overflow"),u==d){for(a=t,o=y;!(a<(s=o<=m?v:m+_<=o?_:o-m));o+=y)p=a-s,f=y-s,l.push(j(P(s+p%f,0))),a=S(p/f);l.push(j(P(a,0))),m=I(t,c,r==i),t=0,++r}++t,++d}return l.join("")}if(n={version:"1.4.1",ucs2:{decode:A,encode:m},decode:g,encode:T,toASCII:function(e){return d(e,function(e){return c.test(e)?"xn--"+T(e):e})},toUnicode:function(e){return d(e,function(e){return u.test(e)?g(e.slice(4).toLowerCase()):e})}},"function"==typeof B&&"object"==_typeof(B.amd)&&B.amd)B("punycode",function(){return n});else if(t&&r)if(C.exports==t)r.exports=n;else for(a in n)n.hasOwnProperty(a)&&(t[a]=n[a]);else e.punycode=n}(this)}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],182:[function(e,t,r){var i=e("buffer").Buffer,n=i.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};r=r.StringDecoder=function(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),function(e){if(e&&!n(e))throw new Error("Unknown encoding: "+e)}(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=o;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=s;break;default:return void(this.write=a)}this.charBuffer=new i(6),this.charReceived=0,this.charLength=0};function a(e){return e.toString(this.encoding)}function o(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function s(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}r.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived>5==6){this.charLength=2;break}if(t<=2&&r>>4==14){this.charLength=3;break}if(t<=3&&r>>3==30){this.charLength=4;break}}this.charReceived=t},r.prototype.end=function(e){var t,r,i="";return e&&e.length&&(i=this.write(e)),this.charReceived&&(t=this.charReceived,r=this.charBuffer,e=this.encoding,i+=r.slice(0,t).toString(e)),i}},{buffer:186}],183:[function(e,t,r){e=e("base-x");t.exports=e("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")},{"base-x":75}],184:[function(e,t,r){t.exports=function(e,t){if("function"==typeof e.compare)return e.compare(t);if(e===t)return 0;for(var r=e.length,i=t.length,n=0,a=Math.min(r,i);n=r())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+r().toString(16)+" bytes");return 0|e}function h(e,t){if(p.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;var r=(e="string"!=typeof e?""+e:e).length;if(0===r)return 0;for(var i=!1;;)switch(t){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return I(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return T(e).length;default:if(i)return I(e).length;t=(""+t).toLowerCase(),i=!0}}function t(e,t,r){var i,n,a,o=!1;if((t=void 0===t||t<0?0:t)>this.length)return"";if((r=void 0===r||r>this.length?this.length:r)<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e=e||"utf8";;)switch(e){case"hex":return function(e,t,r){var i=e.length;(!t||t<0)&&(t=0);(!r||r<0||i=e.length){if(n)return-1;r=e.length-1}else if(r<0){if(!n)return-1;r=0}if("string"==typeof t&&(t=p.from(t,i)),p.isBuffer(t))return 0===t.length?-1:g(e,t,r,i,n);if("number"==typeof t)return t&=255,p.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?(n?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(e,t,r):g(e,[t],r,i,n);throw new TypeError("val must be string, number or Buffer")}function g(e,t,r,i,n){var a=1,o=e.length,s=t.length;if(void 0!==i&&("ucs2"===(i=String(i).toLowerCase())||"ucs-2"===i||"utf16le"===i||"utf-16le"===i)){if(e.length<2||t.length<2)return-1;o/=a=2,s/=2,r/=2}function u(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(n)for(var c=-1,f=r;f>8,i=i%256,n.push(i),n.push(r);return n}(t,e.length-r),e,r,i)}function v(e,t,r){r=Math.min(e.length,r);for(var i=[],n=t;n>>10&1023|55296),f=56320|1023&f),i.push(f),n+=p}return function(e){var t=e.length;if(t<=_)return String.fromCharCode.apply(String,e);var r="",i=0;for(;it&&(e+=" ... ")),""},p.prototype.compare=function(e,t,r,i,n){if(!p.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===r&&(r=e?e.length:0),void 0===i&&(i=0),void 0===n&&(n=this.length),t<0||r>e.length||i<0||n>this.length)throw new RangeError("out of range index");if(n<=i&&r<=t)return 0;if(n<=i)return-1;if(r<=t)return 1;if(this===e)return 0;for(var a=(n>>>=0)-(i>>>=0),o=(r>>>=0)-(t>>>=0),s=Math.min(a,o),u=this.slice(i,n),c=e.slice(t,r),f=0;fthis.length)throw new RangeError("Attempt to write outside buffer bounds");i=i||"utf8";for(var a,o,s,u=!1;;)switch(i){case"hex":return function(e,t,r,i){r=Number(r)||0;var n=e.length-r;if((!i||n<(i=Number(i)))&&(i=n),(n=t.length)%2!=0)throw new TypeError("Invalid hex string");n/2e.length)throw new RangeError("Index out of range")}function x(e,t,r,i){t<0&&(t=65535+t+1);for(var n=0,a=Math.min(e.length-r,2);n>>8*(i?n:1-n)}function S(e,t,r,i){t<0&&(t=4294967295+t+1);for(var n=0,a=Math.min(e.length-r,4);n>>8*(i?n:3-n)&255}function j(e,t,r,i){if(r+i>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function E(e,t,r,i,n){return n||j(e,0,r,4),a.write(e,t,r,i,23,4),r+4}function A(e,t,r,i,n){return n||j(e,0,r,8),a.write(e,t,r,i,52,8),r+8}p.prototype.slice=function(e,t){var r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):r>>8):x(this,e,t,!0),t+2},p.prototype.writeUInt16BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,2,65535,0),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):x(this,e,t,!1),t+2},p.prototype.writeUInt32LE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,4294967295,0),p.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):S(this,e,t,!0),t+4},p.prototype.writeUInt32BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,4294967295,0),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):S(this,e,t,!1),t+4},p.prototype.writeIntLE=function(e,t,r,i){e=+e,t|=0,i||k(this,e,t,r,(i=Math.pow(2,8*r-1))-1,-i);var n=0,a=1,o=0;for(this[t]=255&e;++n>0)-o&255;return t+r},p.prototype.writeIntBE=function(e,t,r,i){e=+e,t|=0,i||k(this,e,t,r,(i=Math.pow(2,8*r-1))-1,-i);var n=r-1,a=1,o=0;for(this[t+n]=255&e;0<=--n&&(a*=256);)e<0&&0===o&&0!==this[t+n+1]&&(o=1),this[t+n]=(e/a>>0)-o&255;return t+r},p.prototype.writeInt8=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,1,127,-128),(e=!p.TYPED_ARRAY_SUPPORT?Math.floor(e):e)<0&&(e=255+e+1),this[t]=255&e,t+1},p.prototype.writeInt16LE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,2,32767,-32768),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):x(this,e,t,!0),t+2},p.prototype.writeInt16BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,2,32767,-32768),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):x(this,e,t,!1),t+2},p.prototype.writeInt32LE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,2147483647,-2147483648),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):S(this,e,t,!0),t+4},p.prototype.writeInt32BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):S(this,e,t,!1),t+4},p.prototype.writeFloatLE=function(e,t,r){return E(this,e,t,!0,r)},p.prototype.writeFloatBE=function(e,t,r){return E(this,e,t,!1,r)},p.prototype.writeDoubleLE=function(e,t,r){return A(this,e,t,!0,r)},p.prototype.writeDoubleBE=function(e,t,r){return A(this,e,t,!1,r)},p.prototype.copy=function(e,t,r,i){if(r=r||0,i||0===i||(i=this.length),t=(t=t>=e.length?e.length:t)||0,(i=0=this.length)throw new RangeError("sourceStart out of bounds");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length);var n,a=(i=e.length-t>>=0,r=void 0===r?this.length:r>>>0,"number"==typeof(e=e||0))for(s=t;s>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;a.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;a.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return a}function T(e){return s.toByteArray(function(e){var t;if((e=((t=e).trim?t.trim():t.replace(/^\s+|\s+$/g,"")).replace(P,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function O(e,t,r,i){for(var n=0;n=t.length||n>=e.length);++n)t[n+r]=e[n];return n}}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},C("buffer").Buffer)},{"base64-js":76,buffer:186,ieee754:295,isarray:299}],187:[function(e,t,r){t.exports={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",208:"Already Reported",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Payload Too Large",414:"URI Too Long",415:"Unsupported Media Type",416:"Range Not Satisfiable",417:"Expectation Failed",418:"I'm a teapot",421:"Misdirected Request",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",425:"Unordered Collection",426:"Upgrade Required",428:"Precondition Required",429:"Too Many Requests",431:"Request Header Fields Too Large",451:"Unavailable For Legal Reasons",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",508:"Loop Detected",509:"Bandwidth Limit Exceeded",510:"Not Extended",511:"Network Authentication Required"}},{}],188:[function(e,t,r){function n(e){this.dict=e||{}}n.prototype.set=function(e,t,r){if("object"!==_typeof(e)){void 0===r&&(r=!0);var i=this.has(e);return!r&&i?this.dict[i]=this.dict[i]+","+t:this.dict[i||e]=t,i}for(var n in e)this.set(n,e[n],t)},n.prototype.has=function(e){for(var t=Object.keys(this.dict),e=e.toLowerCase(),r=0;rr?t=("rmd160"===e?new u:c(e)).update(t).digest():t.length>>1],r=f.r28shl(r,a),i=f.r28shl(i,a);f.pc2(r,i,e.keys,n)}},s.prototype._update=function(e,t,r,i){var n=this._desState,a=f.readUInt32BE(e,t),t=f.readUInt32BE(e,t+4);f.ip(a,t,n.tmp,0),a=n.tmp[0],t=n.tmp[1],"encrypt"===this.type?this._encrypt(n,a,t,n.tmp,0):this._decrypt(n,a,t,n.tmp,0),a=n.tmp[0],t=n.tmp[1],f.writeUInt32BE(r,a,i),f.writeUInt32BE(r,t,i+4)},s.prototype._pad=function(e,t){for(var r=e.length-t,i=t;i>>0,a=c}f.rip(o,a,i,n)},s.prototype._decrypt=function(e,t,r,i,n){for(var a=r,o=t,s=e.keys.length-2;0<=s;s-=2){var u=e.keys[s],c=e.keys[s+1];f.expand(a,e.tmp,0),u^=e.tmp[0],c^=e.tmp[1];u=f.substitute(u,c),c=a,a=(o^f.permute(u))>>>0,o=c}f.rip(a,o,i,n)}},{"./cipher":202,"./utils":205,inherits:296,"minimalistic-assert":324}],204:[function(e,t,r){"use strict";var n=e("minimalistic-assert"),i=e("inherits"),a=e("./cipher"),o=e("./des");function s(e,t){n.equal(t.length,24,"Invalid key length");var r=t.slice(0,8),i=t.slice(8,16),t=t.slice(16,24);this.ciphers="encrypt"===e?[o.create({type:"encrypt",key:r}),o.create({type:"decrypt",key:i}),o.create({type:"encrypt",key:t})]:[o.create({type:"decrypt",key:t}),o.create({type:"encrypt",key:i}),o.create({type:"decrypt",key:r})]}function u(e){a.call(this,e);e=new s(this.type,this.options.key);this._edeState=e}i(u,a),(t.exports=u).create=function(e){return new u(e)},u.prototype._update=function(e,t,r,i){var n=this._edeState;n.ciphers[0]._update(e,t,r,i),n.ciphers[1]._update(r,i,r,i),n.ciphers[2]._update(r,i,r,i)},u.prototype._pad=o.prototype._pad,u.prototype._unpad=o.prototype._unpad},{"./cipher":202,"./des":203,inherits:296,"minimalistic-assert":324}],205:[function(e,t,r){"use strict";r.readUInt32BE=function(e,t){return(e[0+t]<<24|e[1+t]<<16|e[2+t]<<8|e[3+t])>>>0},r.writeUInt32BE=function(e,t,r){e[0+r]=t>>>24,e[1+r]=t>>>16&255,e[2+r]=t>>>8&255,e[3+r]=255&t},r.ip=function(e,t,r,i){for(var n=0,a=0,o=6;0<=o;o-=2){for(var s=0;s<=24;s+=8)n<<=1,n|=t>>>s+o&1;for(s=0;s<=24;s+=8)n<<=1,n|=e>>>s+o&1}for(o=6;0<=o;o-=2){for(s=1;s<=25;s+=8)a<<=1,a|=t>>>s+o&1;for(s=1;s<=25;s+=8)a<<=1,a|=e>>>s+o&1}r[i+0]=n>>>0,r[i+1]=a>>>0},r.rip=function(e,t,r,i){for(var n=0,a=0,o=0;o<4;o++)for(var s=24;0<=s;s-=8)n<<=1,n|=t>>>s+o&1,n<<=1,n|=e>>>s+o&1;for(o=4;o<8;o++)for(s=24;0<=s;s-=8)a<<=1,a|=t>>>s+o&1,a<<=1,a|=e>>>s+o&1;r[i+0]=n>>>0,r[i+1]=a>>>0},r.pc1=function(e,t,r,i){for(var n=0,a=0,o=7;5<=o;o--){for(var s=0;s<=24;s+=8)n<<=1,n|=t>>s+o&1;for(s=0;s<=24;s+=8)n<<=1,n|=e>>s+o&1}for(s=0;s<=24;s+=8)n<<=1,n|=t>>s+o&1;for(o=1;o<=3;o++){for(s=0;s<=24;s+=8)a<<=1,a|=t>>s+o&1;for(s=0;s<=24;s+=8)a<<=1,a|=e>>s+o&1}for(s=0;s<=24;s+=8)a<<=1,a|=e>>s+o&1;r[i+0]=n>>>0,r[i+1]=a>>>0},r.r28shl=function(e,t){return e<>>28-t};var u=[14,11,17,4,27,23,25,0,13,22,7,18,5,9,16,24,2,20,12,21,1,8,15,26,15,4,25,19,9,1,26,16,5,11,23,8,12,7,17,0,22,3,10,14,6,20,27,24];r.pc2=function(e,t,r,i){for(var n=0,a=0,o=u.length>>>1,s=0;s>>u[s]&1;for(s=o;s>>u[s]&1;r[i+0]=n>>>0,r[i+1]=a>>>0},r.expand=function(e,t,r){for(var i=0,n=0,i=(1&e)<<5|e>>>27,a=23;15<=a;a-=4)i<<=6,i|=e>>>a&63;for(a=11;3<=a;a-=4)n|=e>>>a&63,n<<=6;n|=(31&e)<<1|e>>>31,t[r+0]=i>>>0,t[r+1]=n>>>0};var n=[14,0,4,15,13,7,1,4,2,14,15,2,11,13,8,1,3,10,10,6,6,12,12,11,5,9,9,5,0,3,7,8,4,15,1,12,14,8,8,2,13,4,6,9,2,1,11,7,15,5,12,11,9,3,7,14,3,10,10,0,5,6,0,13,15,3,1,13,8,4,14,7,6,15,11,2,3,8,4,14,9,12,7,0,2,1,13,10,12,6,0,9,5,11,10,5,0,13,14,8,7,10,11,1,10,3,4,15,13,4,1,2,5,11,8,6,12,7,6,12,9,0,3,5,2,14,15,9,10,13,0,7,9,0,14,9,6,3,3,4,15,6,5,10,1,2,13,8,12,5,7,14,11,12,4,11,2,15,8,1,13,1,6,10,4,13,9,0,8,6,15,9,3,8,0,7,11,4,1,15,2,14,12,3,5,11,10,5,14,2,7,12,7,13,13,8,14,11,3,5,0,6,6,15,9,0,10,3,1,4,2,7,8,2,5,12,11,1,12,10,4,14,15,9,10,3,6,15,9,0,0,6,12,10,11,1,7,13,13,8,15,9,1,4,3,5,14,11,5,12,2,7,8,2,4,14,2,14,12,11,4,2,1,12,7,4,10,7,11,13,6,1,8,5,5,0,3,15,15,10,13,3,0,9,14,8,9,6,4,11,2,8,1,12,11,7,10,1,13,14,7,2,8,13,15,6,9,15,12,0,5,9,6,10,3,4,0,5,14,3,12,10,1,15,10,4,15,2,9,7,2,12,6,9,8,5,0,6,13,1,3,13,4,14,14,0,7,11,5,3,11,8,9,4,14,3,15,2,5,12,2,9,8,5,12,15,3,10,7,11,0,14,4,1,10,7,1,6,13,0,11,8,6,13,4,13,11,0,2,11,14,7,15,4,0,9,8,1,13,10,3,14,12,3,9,5,7,12,5,2,10,15,6,8,1,6,1,6,4,11,11,13,13,8,12,1,3,4,7,10,14,7,10,9,15,5,6,0,8,15,0,14,5,2,9,3,2,12,13,1,2,15,8,13,4,8,6,10,15,3,11,7,1,4,10,12,9,5,3,6,14,11,5,0,0,14,12,9,7,2,7,2,11,1,4,14,1,7,9,4,12,10,14,8,2,13,0,15,6,12,10,9,13,0,15,3,3,5,5,6,8,11];r.substitute=function(e,t){for(var r=0,i=0;i<4;i++)r<<=4,r|=n[64*i+(e>>>18-6*i&63)];for(i=0;i<4;i++)r<<=4,r|=n[256+64*i+(t>>>18-6*i&63)];return r>>>0};var i=[16,25,12,11,3,20,4,15,31,17,9,6,27,14,1,22,30,24,8,18,0,5,29,23,13,19,2,26,10,21,28,7];r.permute=function(e){for(var t=0,r=0;r>>i[r]&1;return t>>>0},r.padSplit=function(e,t,r){for(var i=e.toString(2);i.lengthe;)r.ishrn(1);if(r.isEven()&&r.iadd(u),r.testn(1)||r.iadd(c),t.cmp(c)){if(!t.cmp(f))for(;r.mod(p).cmp(l);)r.iadd(d)}else for(;r.mod(o).cmp(h);)r.iadd(d);if(g(i=r.shrn(1))&&g(r)&&b(i)&&b(r)&&s.test(i)&&s.test(r))return r}}},{"bn.js":129,"miller-rabin":320,randombytes:386}],209:[function(e,t,r){t.exports={modp1:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"},modp2:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"},modp5:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"},modp14:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"},modp15:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"},modp16:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"},modp17:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"},modp18:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"}}},{}],210:[function(e,t,r){var s=e("crypto"),u=e("jsbn").BigInteger,c=(e("./lib/ec.js").ECPointFp,e("safer-buffer").Buffer);function f(e,t){return e.length>=t?e:f("0"+e,t)}r.ECCurves=e("./lib/sec.js"),r.ECKey=function(e,t,r){var i=e(),n=i.getN(),a=Math.floor(n.bitLength()/8);if(t)if(r){e=i.getCurve();this.P=e.decodePointHex(t.toString("hex"))}else{if(t.length!=a)return!1;o=new u(t.toString("hex"),16)}else{var t=n.subtract(u.ONE),o=new u(s.randomBytes(n.bitLength())).mod(t).add(u.ONE);this.P=i.getG().multiply(o)}this.P&&(this.PublicKey=c.from(i.getCurve().encodeCompressedPointHex(this.P),"hex")),o&&(this.PrivateKey=c.from(f(o.toString(16),2*a),"hex"),this.deriveSharedSecret=function(e){if(!e||!e.P)return!1;e=e.P.multiply(o);return c.from(f(e.getX().toBigInteger().toString(16),2*a),"hex")})}},{"./lib/ec.js":211,"./lib/sec.js":212,crypto:198,jsbn:301,"safer-buffer":422}],211:[function(e,t,r){var p=e("jsbn").BigInteger,i=p.prototype.Barrett;function c(e,t){this.x=t,this.q=e}function u(e,t,r,i){this.curve=e,this.x=t,this.y=r,this.z=null==i?p.ONE:i,this.zinv=null}function n(e,t,r){this.q=e,this.a=this.fromBigInteger(t),this.b=this.fromBigInteger(r),this.infinity=new u(this,null,null),this.reducer=new i(this.q)}c.prototype.equals=function(e){return e==this||this.q.equals(e.q)&&this.x.equals(e.x)},c.prototype.toBigInteger=function(){return this.x},c.prototype.negate=function(){return new c(this.q,this.x.negate().mod(this.q))},c.prototype.add=function(e){return new c(this.q,this.x.add(e.toBigInteger()).mod(this.q))},c.prototype.subtract=function(e){return new c(this.q,this.x.subtract(e.toBigInteger()).mod(this.q))},c.prototype.multiply=function(e){return new c(this.q,this.x.multiply(e.toBigInteger()).mod(this.q))},c.prototype.square=function(){return new c(this.q,this.x.square().mod(this.q))},c.prototype.divide=function(e){return new c(this.q,this.x.multiply(e.toBigInteger().modInverse(this.q)).mod(this.q))},u.prototype.getX=function(){null==this.zinv&&(this.zinv=this.z.modInverse(this.curve.q));var e=this.x.toBigInteger().multiply(this.zinv);return this.curve.reduce(e),this.curve.fromBigInteger(e)},u.prototype.getY=function(){null==this.zinv&&(this.zinv=this.z.modInverse(this.curve.q));var e=this.y.toBigInteger().multiply(this.zinv);return this.curve.reduce(e),this.curve.fromBigInteger(e)},u.prototype.equals=function(e){return e==this||(this.isInfinity()?e.isInfinity():e.isInfinity()?this.isInfinity():!!e.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(e.z)).mod(this.curve.q).equals(p.ZERO)&&e.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(e.z)).mod(this.curve.q).equals(p.ZERO))},u.prototype.isInfinity=function(){return null==this.x&&null==this.y||this.z.equals(p.ZERO)&&!this.y.toBigInteger().equals(p.ZERO)},u.prototype.negate=function(){return new u(this.curve,this.x,this.y.negate(),this.z)},u.prototype.add=function(e){if(this.isInfinity())return e;if(e.isInfinity())return this;var t=e.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(e.z)).mod(this.curve.q),r=e.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(e.z)).mod(this.curve.q);if(p.ZERO.equals(r))return p.ZERO.equals(t)?this.twice():this.curve.getInfinity();var i=new p("3"),n=this.x.toBigInteger(),a=this.y.toBigInteger(),o=(e.x.toBigInteger(),e.y.toBigInteger(),r.square()),s=o.multiply(r),n=n.multiply(o),r=(o=t.square().multiply(this.z)).subtract(n.shiftLeft(1)).multiply(e.z).subtract(s).multiply(r).mod(this.curve.q),t=n.multiply(i).multiply(t).subtract(a.multiply(s)).subtract(o.multiply(t)).multiply(e.z).add(t.multiply(s)).mod(this.curve.q),e=s.multiply(this.z).multiply(e.z).mod(this.curve.q);return new u(this.curve,this.curve.fromBigInteger(r),this.curve.fromBigInteger(t),e)},u.prototype.twice=function(){if(this.isInfinity())return this;if(0==this.y.toBigInteger().signum())return this.curve.getInfinity();var e=new p("3"),t=this.x.toBigInteger(),r=this.y.toBigInteger(),i=(a=r.multiply(this.z)).multiply(r).mod(this.curve.q),n=this.curve.a.toBigInteger(),r=t.square().multiply(e),n=(r=(r=!p.ZERO.equals(n)?r.add(this.z.square().multiply(n)):r).mod(this.curve.q)).square().subtract(t.shiftLeft(3).multiply(i)).shiftLeft(1).multiply(a).mod(this.curve.q),r=r.multiply(e).multiply(t).subtract(i.shiftLeft(1)).shiftLeft(2).multiply(i).subtract(r.square().multiply(r)).mod(this.curve.q),a=a.square().multiply(a).shiftLeft(3).mod(this.curve.q);return new u(this.curve,this.curve.fromBigInteger(n),this.curve.fromBigInteger(r),a)},u.prototype.multiply=function(e){if(this.isInfinity())return this;if(0==e.signum())return this.curve.getInfinity();for(var t=e,r=t.multiply(new p("3")),i=this.negate(),n=this,a=r.bitLength()-2;0r.bitLength()?e.bitLength()-1:r.bitLength()-1,n=this.curve.getInfinity(),a=this.add(t);0<=i;)n=n.twice(),e.testBit(i)?n=r.testBit(i)?n.add(a):n.add(this):r.testBit(i)&&(n=n.add(t)),--i;return n},n.prototype.getQ=function(){return this.q},n.prototype.getA=function(){return this.a},n.prototype.getB=function(){return this.b},n.prototype.equals=function(e){return e==this||this.q.equals(e.q)&&this.a.equals(e.a)&&this.b.equals(e.b)},n.prototype.getInfinity=function(){return this.infinity},n.prototype.fromBigInteger=function(e){return new c(this.q,e)},n.prototype.reduce=function(e){this.reducer.reduce(e)},n.prototype.encodePointHex=function(e){if(e.isInfinity())return"00";var t=e.getX().toBigInteger().toString(16),r=e.getY().toBigInteger().toString(16),i=this.getQ().toString(16).length;for(i%2!=0&&i++;t.lengtht+1;){var r=e.shiftRight(t),i=e.subtract(r.shiftLeft(t));e=(r=!this.getR().equals(p.ONE)?r.multiply(this.getR()):r).add(i)}for(;0<=e.compareTo(q);)e=e.subtract(q)}else e=e.mod(q);return e},c.prototype.sqrt=function(){if(!this.q.testBit(0))throw"unsupported";if(this.q.testBit(1)){var e=new c(this.q,this.x.modPow(this.q.shiftRight(2).add(p.ONE),this.q));return e.square().equals(this)?e:null}var t=this.q.subtract(p.ONE),r=t.shiftRight(1);if(!this.x.modPow(r,this.q).equals(p.ONE))return null;var i,n=t.shiftRight(2).shiftLeft(1).add(p.ONE),a=this.x,o=modDouble(modDouble(a));do{for(;i=new p(this.q.bitLength(),new SecureRandom),0<=i.compareTo(this.q)||!i.multiply(i).subtract(o).modPow(r,this.q).equals(t););var s=this.lucasSequence(i,a,n),u=s[0],s=s[1];if(this.modMult(s,s).equals(o))return s=(s=s.testBit(0)?s.add(q):s).shiftRight(1),new c(q,s)}while(u.equals(p.ONE)||u.equals(t));return null},c.prototype.lucasSequence=function(e,t,r){for(var i=r.bitLength(),n=r.getLowestSetBit(),a=p.ONE,o=p.TWO,s=e,u=p.ONE,c=p.ONE,f=i-1;n+1<=f;--f)u=this.modMult(u,c),r.testBit(f)?(c=this.modMult(u,t),a=this.modMult(a,s),o=this.modReduce(s.multiply(o).subtract(e.multiply(u))),s=this.modReduce(s.multiply(s).subtract(c.shiftLeft(1)))):(c=u,a=this.modReduce(a.multiply(o).subtract(u)),s=this.modReduce(s.multiply(o).subtract(e.multiply(u))),o=this.modReduce(o.multiply(o).subtract(u.shiftLeft(1))));u=this.modMult(u,c),c=this.modMult(u,t),a=this.modReduce(a.multiply(o).subtract(u)),o=this.modReduce(s.multiply(o).subtract(e.multiply(u))),u=this.modMult(u,c);for(f=1;f<=n;++f)a=this.modMult(a,o),o=this.modReduce(o.multiply(o).subtract(u.shiftLeft(1))),u=this.modMult(u,u);return[a,o]};r={ECCurveFp:n,ECPointFp:u,ECFieldElementFp:c};t.exports=r},{jsbn:301}],212:[function(e,t,r){var a=e("jsbn").BigInteger,o=e("./ec.js").ECCurveFp;function s(e,t,r,i){this.curve=e,this.g=t,this.n=r,this.h=i}function u(e){return new a(e,16)}function i(){var e=u("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"),t=u("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"),r=u("E87579C11079F43DD824993C2CEE5ED3"),i=u("FFFFFFFE0000000075A30D1B9038A115"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83");return new s(t,r,i,n)}function n(){var e=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"),t=a.ZERO,r=u("7"),i=u("0100000000000000000001B8FA16DFAB9ACA16B6B3"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE");return new s(t,r,i,n)}function c(){var e=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"),t=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"),r=u("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"),i=u("0100000000000000000001F4C8F927AED3CA752257"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32");return new s(t,r,i,n)}function f(){var e=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"),t=a.ZERO,r=u("3"),i=u("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D");return new s(t,r,i,n)}function p(){var e=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"),t=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"),r=u("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"),i=u("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811");return new s(t,r,i,n)}function l(){var e=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"),t=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"),r=u("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"),i=u("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34");return new s(t,r,i,n)}function h(){var e=u("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"),t=u("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"),r=u("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"),i=u("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"),n=a.ONE,t=new o(e,t,r),r=t.decodePointHex("046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5");return new s(t,r,i,n)}s.prototype.getCurve=function(){return this.curve},s.prototype.getG=function(){return this.g},s.prototype.getN=function(){return this.n},s.prototype.getH=function(){return this.h},t.exports={secp128r1:i,secp160k1:n,secp160r1:c,secp192k1:f,secp192r1:p,secp224r1:l,secp256r1:h}},{"./ec.js":211,jsbn:301}],213:[function(e,t,r){"use strict";r.version=e("../package.json").version,r.utils=e("./elliptic/utils"),r.rand=e("brorand"),r.curve=e("./elliptic/curve"),r.curves=e("./elliptic/curves"),r.ec=e("./elliptic/ec"),r.eddsa=e("./elliptic/eddsa")},{"../package.json":228,"./elliptic/curve":216,"./elliptic/curves":219,"./elliptic/ec":220,"./elliptic/eddsa":223,"./elliptic/utils":227,brorand:131}],214:[function(e,t,r){"use strict";var i=e("bn.js"),n=e("../utils"),j=n.getNAF,E=n.getJSF,f=n.assert;function a(e,t){this.type=e,this.p=new i(t.p,16),this.red=t.prime?i.red(t.prime):i.mont(this.p),this.zero=new i(0).toRed(this.red),this.one=new i(1).toRed(this.red),this.two=new i(2).toRed(this.red),this.n=t.n&&new i(t.n,16),this.g=t.g&&this.pointFromJSON(t.g,t.gRed),this._wnafT1=new Array(4),this._wnafT2=new Array(4),this._wnafT3=new Array(4),this._wnafT4=new Array(4),this._bitLength=this.n?this.n.bitLength():0;t=this.n&&this.p.div(this.n);!t||0>1]):o.mixedAdd(n[-u-1>>1].neg()):0>1]):o.add(n[-u-1>>1].neg())}return"affine"===e.type?o.toP():o},a.prototype._wnafMulAdd=function(e,t,r,i,n){for(var a=this._wnafT1,o=this._wnafT2,s=this._wnafT3,u=0,c=0;c>1]:S<0&&(x=o[g][-S-1>>1].neg()),v="affine"===x.type?v.mixedAdd(x):v.add(x))}}for(c=0;c=Math.ceil((e.bitLength()+1)/t.step)},o.prototype._getDoubles=function(e,t){if(this.precomputed&&this.precomputed.doubles)return this.precomputed.doubles;for(var r=[this],i=this,n=0;n":""},c.prototype.isInfinity=function(){return 0===this.x.cmpn(0)&&(0===this.y.cmp(this.z)||this.zOne&&0===this.y.cmp(this.curve.c))},c.prototype._extDbl=function(){var e=this.x.redSqr(),t=this.y.redSqr(),r=(r=this.z.redSqr()).redIAdd(r),i=this.curve._mulA(e),n=this.x.redAdd(this.y).redSqr().redISub(e).redISub(t),a=i.redAdd(t),e=a.redSub(r),r=i.redSub(t),i=n.redMul(e),t=a.redMul(r),r=n.redMul(r),a=e.redMul(a);return this.curve.point(i,t,a,r)},c.prototype._projDbl=function(){var e,t,r,i,n,a,o=this.x.redAdd(this.y).redSqr(),s=this.x.redSqr(),u=this.y.redSqr();return a=this.curve.twisted?(e=(i=this.curve._mulA(s)).redAdd(u),this.zOne?(t=o.redSub(s).redSub(u).redMul(e.redSub(this.curve.two)),r=e.redMul(i.redSub(u)),e.redSqr().redSub(e).redSub(e)):(n=this.z.redSqr(),a=e.redSub(n).redISub(n),t=o.redSub(s).redISub(u).redMul(a),r=e.redMul(i.redSub(u)),e.redMul(a))):(i=s.redAdd(u),n=this.curve._mulC(this.z).redSqr(),a=i.redSub(n).redSub(n),t=this.curve._mulC(o.redISub(i)).redMul(a),r=this.curve._mulC(i).redMul(s.redISub(u)),i.redMul(a)),this.curve.point(t,r,a)},c.prototype.dbl=function(){return this.isInfinity()?this:this.curve.extended?this._extDbl():this._projDbl()},c.prototype._extAdd=function(e){var t=this.y.redSub(this.x).redMul(e.y.redSub(e.x)),r=this.y.redAdd(this.x).redMul(e.y.redAdd(e.x)),i=this.t.redMul(this.curve.dd).redMul(e.t),n=this.z.redMul(e.z.redAdd(e.z)),a=r.redSub(t),e=n.redSub(i),n=n.redAdd(i),i=r.redAdd(t),r=a.redMul(e),t=n.redMul(i),i=a.redMul(i),n=e.redMul(n);return this.curve.point(r,t,n,i)},c.prototype._projAdd=function(e){var t,r=this.z.redMul(e.z),i=r.redSqr(),n=this.x.redMul(e.x),a=this.y.redMul(e.y),o=this.curve.d.redMul(n).redMul(a),s=i.redSub(o),o=i.redAdd(o),e=this.x.redAdd(this.y).redMul(e.x.redAdd(e.y)).redISub(n).redISub(a),e=r.redMul(s).redMul(e),o=this.curve.twisted?(t=r.redMul(o).redMul(a.redSub(this.curve._mulA(n))),s.redMul(o)):(t=r.redMul(o).redMul(a.redSub(n)),this.curve._mulC(s).redMul(o));return this.curve.point(e,t,o)},c.prototype.add=function(e){return this.isInfinity()?e:e.isInfinity()?this:this.curve.extended?this._extAdd(e):this._projAdd(e)},c.prototype.mul=function(e){return this._hasDoubles(e)?this.curve._fixedNafMul(this,e):this.curve._wnafMul(this,e)},c.prototype.mulAdd=function(e,t,r){return this.curve._wnafMulAdd(1,[this,t],[e,r],2,!1)},c.prototype.jmulAdd=function(e,t,r){return this.curve._wnafMulAdd(1,[this,t],[e,r],2,!0)},c.prototype.normalize=function(){if(this.zOne)return this;var e=this.z.redInvm();return this.x=this.x.redMul(e),this.y=this.y.redMul(e),this.t&&(this.t=this.t.redMul(e)),this.z=this.curve.one,this.zOne=!0,this},c.prototype.neg=function(){return this.curve.point(this.x.redNeg(),this.y,this.z,this.t&&this.t.redNeg())},c.prototype.getX=function(){return this.normalize(),this.x.fromRed()},c.prototype.getY=function(){return this.normalize(),this.y.fromRed()},c.prototype.eq=function(e){return this===e||0===this.getX().cmp(e.getX())&&0===this.getY().cmp(e.getY())},c.prototype.eqXToP=function(e){var t=e.toRed(this.curve.red).redMul(this.z);if(0===this.x.cmp(t))return!0;for(var r=e.clone(),i=this.curve.redN.redMul(this.z);;){if(r.iadd(this.curve.n),0<=r.cmp(this.curve.p))return!1;if(t.redIAdd(i),0===this.x.cmp(t))return!0}},c.prototype.toP=c.prototype.normalize,c.prototype.mixedAdd=c.prototype.add},{"../utils":227,"./base":214,"bn.js":129,inherits:296}],216:[function(e,t,r){"use strict";r.base=e("./base"),r.short=e("./short"),r.mont=e("./mont"),r.edwards=e("./edwards")},{"./base":214,"./edwards":215,"./mont":217,"./short":218}],217:[function(e,t,r){"use strict";var i=e("bn.js"),n=e("inherits"),a=e("./base"),o=e("../utils");function s(e){a.call(this,"mont",e),this.a=new i(e.a,16).toRed(this.red),this.b=new i(e.b,16).toRed(this.red),this.i4=new i(4).toRed(this.red).redInvm(),this.two=new i(2).toRed(this.red),this.a24=this.i4.redMul(this.a.redAdd(this.two))}function u(e,t,r){a.BasePoint.call(this,e,"projective"),null===t&&null===r?(this.x=this.curve.one,this.z=this.curve.zero):(this.x=new i(t,16),this.z=new i(r,16),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)))}n(s,a),(t.exports=s).prototype.validate=function(e){var t=e.normalize().x,e=t.redSqr(),t=e.redMul(t).redAdd(e.redMul(this.a)).redAdd(t);return 0===t.redSqrt().redSqr().cmp(t)},n(u,a.BasePoint),s.prototype.decodePoint=function(e,t){return this.point(o.toArray(e,t),1)},s.prototype.point=function(e,t){return new u(this,e,t)},s.prototype.pointFromJSON=function(e){return u.fromJSON(this,e)},u.prototype.precompute=function(){},u.prototype._encode=function(){return this.getX().toArray("be",this.curve.p.byteLength())},u.fromJSON=function(e,t){return new u(e,t[0],t[1]||e.one)},u.prototype.inspect=function(){return this.isInfinity()?"":""},u.prototype.isInfinity=function(){return 0===this.z.cmpn(0)},u.prototype.dbl=function(){var e=this.x.redAdd(this.z).redSqr(),t=this.x.redSub(this.z).redSqr(),r=e.redSub(t),e=e.redMul(t),r=r.redMul(t.redAdd(this.curve.a24.redMul(r)));return this.curve.point(e,r)},u.prototype.add=function(){throw new Error("Not supported on Montgomery curve")},u.prototype.diffAdd=function(e,t){var r=this.x.redAdd(this.z),i=this.x.redSub(this.z),n=e.x.redAdd(e.z),r=e.x.redSub(e.z).redMul(r),n=n.redMul(i),i=t.z.redMul(r.redAdd(n).redSqr()),n=t.x.redMul(r.redISub(n).redSqr());return this.curve.point(i,n)},u.prototype.mul=function(e){for(var t=e.clone(),r=this,i=this.curve.point(null,null),n=[];0!==t.cmpn(0);t.iushrn(1))n.push(t.andln(1));for(var a=n.length-1;0<=a;a--)0===n[a]?(r=r.diffAdd(i,this),i=i.dbl()):(i=r.diffAdd(i,this),r=r.dbl());return i},u.prototype.mulAdd=function(){throw new Error("Not supported on Montgomery curve")},u.prototype.jumlAdd=function(){throw new Error("Not supported on Montgomery curve")},u.prototype.eq=function(e){return 0===this.getX().cmp(e.getX())},u.prototype.normalize=function(){return this.x=this.x.redMul(this.z.redInvm()),this.z=this.curve.one,this},u.prototype.getX=function(){return this.normalize(),this.x.fromRed()}},{"../utils":227,"./base":214,"bn.js":129,inherits:296}],218:[function(e,t,r){"use strict";var i=e("../utils"),v=e("bn.js"),n=e("inherits"),a=e("./base"),o=i.assert;function s(e){a.call(this,"short",e),this.a=new v(e.a,16).toRed(this.red),this.b=new v(e.b,16).toRed(this.red),this.tinv=this.two.redInvm(),this.zeroA=0===this.a.fromRed().cmpn(0),this.threeA=0===this.a.fromRed().sub(this.p).cmpn(-3),this.endo=this._getEndomorphism(e),this._endoWnafT1=new Array(4),this._endoWnafT2=new Array(4)}function u(e,t,r,i){a.BasePoint.call(this,e,"affine"),null===t&&null===r?(this.x=null,this.y=null,this.inf=!0):(this.x=new v(t,16),this.y=new v(r,16),i&&(this.x.forceRed(this.curve.red),this.y.forceRed(this.curve.red)),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.y.red||(this.y=this.y.toRed(this.curve.red)),this.inf=!1)}function c(e,t,r,i){a.BasePoint.call(this,e,"jacobian"),null===t&&null===r&&null===i?(this.x=this.curve.one,this.y=this.curve.one,this.z=new v(0)):(this.x=new v(t,16),this.y=new v(r,16),this.z=new v(i,16)),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.y.red||(this.y=this.y.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)),this.zOne=this.z===this.curve.one}n(s,a),(t.exports=s).prototype._getEndomorphism=function(e){var t,r,i;if(this.zeroA&&this.g&&this.n&&1===this.p.modn(3))return r=(e.beta?new v(e.beta,16):r=(i=this._getEndoRoots(this.p))[0].cmp(i[1])<0?i[0]:i[1]).toRed(this.red),e.lambda?t=new v(e.lambda,16):(i=this._getEndoRoots(this.n),0===this.g.mul(i[0]).x.cmp(this.g.x.redMul(r))?t=i[0]:(t=i[1],o(0===this.g.mul(t).x.cmp(this.g.x.redMul(r))))),{beta:r,lambda:t,basis:e.basis?e.basis.map(function(e){return{a:new v(e.a,16),b:new v(e.b,16)}}):this._getEndoBasis(t)}},s.prototype._getEndoRoots=function(e){var t=e===this.p?this.red:v.mont(e),r=new v(2).toRed(t).redInvm(),e=r.redNeg(),r=new v(3).toRed(t).redNeg().redSqrt().redMul(r);return[e.redAdd(r).fromRed(),e.redSub(r).fromRed()]},s.prototype._getEndoBasis=function(e){for(var t,r,i,n,a,o,s,u=this.n.ushrn(Math.floor(this.n.bitLength()/2)),c=e,f=this.n.clone(),p=new v(1),l=new v(0),h=new v(0),d=new v(1),m=0;0!==c.cmpn(0);){var g=f.div(c),b=f.sub(g.mul(c)),y=h.sub(g.mul(p)),g=d.sub(g.mul(l));if(!i&&b.cmp(u)<0)t=s.neg(),r=p,i=b.neg(),n=y;else if(i&&2==++m)break;f=c,c=s=b,h=p,p=y,d=l,l=g}a=b.neg(),o=y;e=i.sqr().add(n.sqr());return 0<=a.sqr().add(o.sqr()).cmp(e)&&(a=t,o=r),i.negative&&(i=i.neg(),n=n.neg()),a.negative&&(a=a.neg(),o=o.neg()),[{a:i,b:n},{a:a,b:o}]},s.prototype._endoSplit=function(e){var t=this.endo.basis,r=t[0],i=t[1],n=i.b.mul(e).divRound(this.n),a=r.b.neg().mul(e).divRound(this.n),o=n.mul(r.a),t=a.mul(i.a),r=n.mul(r.b),i=a.mul(i.b);return{k1:e.sub(o).sub(t),k2:r.add(i).neg()}},s.prototype.pointFromX=function(e,t){var r=(e=!(e=new v(e,16)).red?e.toRed(this.red):e).redSqr().redMul(e).redIAdd(e.redMul(this.a)).redIAdd(this.b),i=r.redSqrt();if(0!==i.redSqr().redSub(r).cmp(this.zero))throw new Error("invalid point");r=i.fromRed().isOdd();return(t&&!r||!t&&r)&&(i=i.redNeg()),this.point(e,i)},s.prototype.validate=function(e){if(e.inf)return!0;var t=e.x,r=e.y,e=this.a.redMul(t),e=t.redSqr().redMul(t).redIAdd(e).redIAdd(this.b);return 0===r.redSqr().redISub(e).cmpn(0)},s.prototype._endoWnafMulAdd=function(e,t,r){for(var i=this._endoWnafT1,n=this._endoWnafT2,a=0;a":""},u.prototype.isInfinity=function(){return this.inf},u.prototype.add=function(e){if(this.inf)return e;if(e.inf)return this;if(this.eq(e))return this.dbl();if(this.neg().eq(e))return this.curve.point(null,null);if(0===this.x.cmp(e.x))return this.curve.point(null,null);var t=this.y.redSub(e.y),e=(t=0!==t.cmpn(0)?t.redMul(this.x.redSub(e.x).redInvm()):t).redSqr().redISub(this.x).redISub(e.x),t=t.redMul(this.x.redSub(e)).redISub(this.y);return this.curve.point(e,t)},u.prototype.dbl=function(){if(this.inf)return this;var e=this.y.redAdd(this.y);if(0===e.cmpn(0))return this.curve.point(null,null);var t=this.curve.a,r=this.x.redSqr(),e=e.redInvm(),t=r.redAdd(r).redIAdd(r).redIAdd(t).redMul(e),e=t.redSqr().redISub(this.x.redAdd(this.x)),t=t.redMul(this.x.redSub(e)).redISub(this.y);return this.curve.point(e,t)},u.prototype.getX=function(){return this.x.fromRed()},u.prototype.getY=function(){return this.y.fromRed()},u.prototype.mul=function(e){return e=new v(e,16),this.isInfinity()?this:this._hasDoubles(e)?this.curve._fixedNafMul(this,e):this.curve.endo?this.curve._endoWnafMulAdd([this],[e]):this.curve._wnafMul(this,e)},u.prototype.mulAdd=function(e,t,r){t=[this,t],r=[e,r];return this.curve.endo?this.curve._endoWnafMulAdd(t,r):this.curve._wnafMulAdd(1,t,r,2)},u.prototype.jmulAdd=function(e,t,r){t=[this,t],r=[e,r];return this.curve.endo?this.curve._endoWnafMulAdd(t,r,!0):this.curve._wnafMulAdd(1,t,r,2,!0)},u.prototype.eq=function(e){return this===e||this.inf===e.inf&&(this.inf||0===this.x.cmp(e.x)&&0===this.y.cmp(e.y))},u.prototype.neg=function(e){if(this.inf)return this;var t,r=this.curve.point(this.x,this.y.redNeg());return e&&this.precomputed&&(t=this.precomputed,e=function(e){return e.neg()},r.precomputed={naf:t.naf&&{wnd:t.naf.wnd,points:t.naf.points.map(e)},doubles:t.doubles&&{step:t.doubles.step,points:t.doubles.points.map(e)}}),r},u.prototype.toJ=function(){return this.inf?this.curve.jpoint(null,null,null):this.curve.jpoint(this.x,this.y,this.curve.one)},n(c,a.BasePoint),s.prototype.jpoint=function(e,t,r){return new c(this,e,t,r)},c.prototype.toP=function(){if(this.isInfinity())return this.curve.point(null,null);var e=this.z.redInvm(),t=e.redSqr(),r=this.x.redMul(t),e=this.y.redMul(t).redMul(e);return this.curve.point(r,e)},c.prototype.neg=function(){return this.curve.jpoint(this.x,this.y.redNeg(),this.z)},c.prototype.add=function(e){if(this.isInfinity())return e;if(e.isInfinity())return this;var t=e.z.redSqr(),r=this.z.redSqr(),i=this.x.redMul(t),n=e.x.redMul(r),a=this.y.redMul(t.redMul(e.z)),o=e.y.redMul(r.redMul(this.z)),t=i.redSub(n),r=a.redSub(o);if(0===t.cmpn(0))return 0!==r.cmpn(0)?this.curve.jpoint(null,null,null):this.dbl();n=t.redSqr(),o=n.redMul(t),i=i.redMul(n),n=r.redSqr().redIAdd(o).redISub(i).redISub(i),o=r.redMul(i.redISub(n)).redISub(a.redMul(o)),t=this.z.redMul(e.z).redMul(t);return this.curve.jpoint(n,o,t)},c.prototype.mixedAdd=function(e){if(this.isInfinity())return e.toJ();if(e.isInfinity())return this;var t=this.z.redSqr(),r=this.x,i=e.x.redMul(t),n=this.y,a=e.y.redMul(t).redMul(this.z),e=r.redSub(i),t=n.redSub(a);if(0===e.cmpn(0))return 0!==t.cmpn(0)?this.curve.jpoint(null,null,null):this.dbl();i=e.redSqr(),a=i.redMul(e),r=r.redMul(i),i=t.redSqr().redIAdd(a).redISub(r).redISub(r),a=t.redMul(r.redISub(i)).redISub(n.redMul(a)),e=this.z.redMul(e);return this.curve.jpoint(i,a,e)},c.prototype.dblp=function(e){if(0===e)return this;if(this.isInfinity())return this;if(!e)return this.dbl();if(this.curve.zeroA||this.curve.threeA){for(var t=this,r=0;r":""},c.prototype.isInfinity=function(){return 0===this.z.cmpn(0)}},{"../utils":227,"./base":214,"bn.js":129,inherits:296}],219:[function(e,t,r){"use strict";var i,n=r,r=e("hash.js"),a=e("./curve"),o=e("./utils").assert;function s(e){"short"===e.type?this.curve=new a.short(e):"edwards"===e.type?this.curve=new a.edwards(e):this.curve=new a.mont(e),this.g=this.curve.g,this.n=this.curve.n,this.hash=e.hash,o(this.g.validate(),"Invalid curve"),o(this.g.mul(this.n).isInfinity(),"Invalid curve, G*N != O")}function u(t,r){Object.defineProperty(n,t,{configurable:!0,enumerable:!0,get:function(){var e=new s(r);return Object.defineProperty(n,t,{configurable:!0,enumerable:!0,value:e}),e}})}n.PresetCurve=s,u("p192",{type:"short",prime:"p192",p:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff",a:"ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc",b:"64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1",n:"ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831",hash:r.sha256,gRed:!1,g:["188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012","07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811"]}),u("p224",{type:"short",prime:"p224",p:"ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001",a:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe",b:"b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4",n:"ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d",hash:r.sha256,gRed:!1,g:["b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21","bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34"]}),u("p256",{type:"short",prime:null,p:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff",a:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc",b:"5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b",n:"ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551",hash:r.sha256,gRed:!1,g:["6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296","4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5"]}),u("p384",{type:"short",prime:null,p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 ffffffff",a:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 fffffffc",b:"b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef",n:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 f4372ddf 581a0db2 48b0a77a ecec196a ccc52973",hash:r.sha384,gRed:!1,g:["aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7","3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f"]}),u("p521",{type:"short",prime:null,p:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff",a:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffc",b:"00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b 99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd 3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00",n:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409",hash:r.sha512,gRed:!1,g:["000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66","00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 3fad0761 353c7086 a272c240 88be9476 9fd16650"]}),u("curve25519",{type:"mont",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"76d06",b:"1",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:r.sha256,gRed:!1,g:["9"]}),u("ed25519",{type:"edwards",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"-1",c:"1",d:"52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:r.sha256,gRed:!1,g:["216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a","6666666666666666666666666666666666666666666666666666666666666658"]});try{i=e("./precomputed/secp256k1")}catch(e){i=void 0}u("secp256k1",{type:"short",prime:"k256",p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f",a:"0",b:"7",n:"ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141",h:"1",hash:r.sha256,beta:"7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee",lambda:"5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72",basis:[{a:"3086d221a7d46bcde86c90e49284eb15",b:"-e4437ed6010e88286f547fa90abfe4c3"},{a:"114ca50f7a8e2f3f657c1108d9d44cfd8",b:"3086d221a7d46bcde86c90e49284eb15"}],gRed:!1,g:["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",i]})},{"./curve":216,"./precomputed/secp256k1":226,"./utils":227,"hash.js":275}],220:[function(e,t,r){"use strict";var l=e("bn.js"),h=e("hmac-drbg"),i=e("../utils"),n=e("../curves"),a=e("brorand"),s=i.assert,o=e("./key"),d=e("./signature");function u(e){if(!(this instanceof u))return new u(e);"string"==typeof e&&(s(n.hasOwnProperty(e),"Unknown curve "+e),e=n[e]),e instanceof n.PresetCurve&&(e={curve:e}),this.curve=e.curve.curve,this.n=this.curve.n,this.nh=this.n.ushrn(1),this.g=this.curve.g,this.g=e.curve.g,this.g.precompute(e.curve.n.bitLength()+1),this.hash=e.hash||e.curve.hash}(t.exports=u).prototype.keyPair=function(e){return new o(this,e)},u.prototype.keyFromPrivate=function(e,t){return o.fromPrivate(this,e,t)},u.prototype.keyFromPublic=function(e,t){return o.fromPublic(this,e,t)},u.prototype.genKeyPair=function(e){e=e||{};for(var t=new h({hash:this.hash,pers:e.pers,persEnc:e.persEnc||"utf8",entropy:e.entropy||a(this.hash.hmacStrength),entropyEnc:e.entropy&&e.entropyEnc||"utf8",nonce:this.n.toArray()}),r=this.n.byteLength(),i=this.n.sub(new l(2));;){var n=new l(t.generate(r));if(!(0>1;if(0<=o.cmp(this.curve.p.umod(this.curve.n))&&r)throw new Error("Unable to find sencond key candinate");o=r?this.curve.pointFromX(o.add(this.curve.n),e):this.curve.pointFromX(o,e);t=t.r.invm(n),a=n.sub(a).mul(t).umod(n),n=i.mul(t).umod(n);return this.g.mulAdd(a,o,n)},u.prototype.getKeyRecoveryParam=function(e,t,r,i){if(null!==(t=new d(t,i)).recoveryParam)return t.recoveryParam;for(var n,a=0;a<4;a++){try{n=this.recoverPubKey(e,t,a)}catch(e){continue}if(n.eq(r))return a}throw new Error("Unable to find valid recovery factor")}},{"../curves":219,"../utils":227,"./key":221,"./signature":222,"bn.js":129,brorand:131,"hmac-drbg":288}],221:[function(e,t,r){"use strict";var i=e("bn.js"),n=e("../utils").assert;function a(e,t){this.ec=e,this.priv=null,this.pub=null,t.priv&&this._importPrivate(t.priv,t.privEnc),t.pub&&this._importPublic(t.pub,t.pubEnc)}(t.exports=a).fromPublic=function(e,t,r){return t instanceof a?t:new a(e,{pub:t,pubEnc:r})},a.fromPrivate=function(e,t,r){return t instanceof a?t:new a(e,{priv:t,privEnc:r})},a.prototype.validate=function(){var e=this.getPublic();return e.isInfinity()?{result:!1,reason:"Invalid public key"}:e.validate()?e.mul(this.ec.curve.n).isInfinity()?{result:!0,reason:null}:{result:!1,reason:"Public key * N != O"}:{result:!1,reason:"Public key is not a point"}},a.prototype.getPublic=function(e,t){return"string"==typeof e&&(t=e,e=null),this.pub||(this.pub=this.ec.g.mul(this.priv)),t?this.pub.encode(t,e):this.pub},a.prototype.getPrivate=function(e){return"hex"===e?this.priv.toString(16,2):this.priv},a.prototype._importPrivate=function(e,t){this.priv=new i(e,t||16),this.priv=this.priv.umod(this.ec.curve.n)},a.prototype._importPublic=function(e,t){if(e.x||e.y)return"mont"===this.ec.curve.type?n(e.x,"Need x coordinate"):"short"!==this.ec.curve.type&&"edwards"!==this.ec.curve.type||n(e.x&&e.y,"Need both x and y coordinate"),void(this.pub=this.ec.curve.point(e.x,e.y));this.pub=this.ec.curve.decodePoint(e,t)},a.prototype.derive=function(e){return e.mul(this.priv).getX()},a.prototype.sign=function(e,t,r){return this.ec.sign(e,this,t,r)},a.prototype.verify=function(e,t){return this.ec.verify(e,t,this)},a.prototype.inspect=function(){return""}},{"../utils":227,"bn.js":129}],222:[function(e,t,r){"use strict";var n=e("bn.js"),a=e("../utils"),i=a.assert;function o(e,t){if(e instanceof o)return e;this._importDER(e,t)||(i(e.r&&e.s,"Signature without r or s"),this.r=new n(e.r,16),this.s=new n(e.s,16),void 0===e.recoveryParam?this.recoveryParam=null:this.recoveryParam=e.recoveryParam)}function s(){this.place=0}function u(e,t){var r=e[t.place++];if(!(128&r))return r;var i=15&r;if(0==i||4>>=0;return!(n<=127)&&(t.place=o,n)}function c(e){for(var t=0,r=e.length-1;!e[t]&&!(128&e[t+1])&&t>>3);for(e.push(128|r);--r;)e.push(t>>>(r<<3)&255);e.push(t)}}(t.exports=o).prototype._importDER=function(e,t){e=a.toArray(e,t);var r=new s;if(48!==e[r.place++])return!1;var i=u(e,r);if(!1===i)return!1;if(i+r.place!==e.length)return!1;if(2!==e[r.place++])return!1;t=u(e,r);if(!1===t)return!1;i=e.slice(r.place,t+r.place);if(r.place+=t,2!==e[r.place++])return!1;t=u(e,r);if(!1===t)return!1;if(e.length!==t+r.place)return!1;r=e.slice(r.place,t+r.place);if(0===i[0]){if(!(128&i[1]))return!1;i=i.slice(1)}if(0===r[0]){if(!(128&r[1]))return!1;r=r.slice(1)}return this.r=new n(i),this.s=new n(r),!(this.recoveryParam=null)},o.prototype.toDER=function(e){var t=this.r.toArray(),r=this.s.toArray();for(128&t[0]&&(t=[0].concat(t)),128&r[0]&&(r=[0].concat(r)),t=c(t),r=c(r);!(r[0]||128&r[1]);)r=r.slice(1);var i=[2];f(i,t.length),(i=i.concat(t)).push(2),f(i,r.length);t=i.concat(r),i=[48];return f(i,t.length),i=i.concat(t),a.encode(i,e)}},{"../utils":227,"bn.js":129}],223:[function(e,t,r){"use strict";var i=e("hash.js"),n=e("../curves"),a=e("../utils"),o=a.assert,s=a.parseBytes,u=e("./key"),c=e("./signature");function f(e){if(o("ed25519"===e,"only tested with ed25519 so far"),!(this instanceof f))return new f(e);e=n[e].curve;this.curve=e,this.g=e.g,this.g.precompute(e.n.bitLength()+1),this.pointClass=e.point().constructor,this.encodingLength=Math.ceil(e.n.bitLength()/8),this.hash=i.sha512}(t.exports=f).prototype.sign=function(e,t){e=s(e);var r=this.keyFromSecret(t),i=this.hashInt(r.messagePrefix(),e),n=this.g.mul(i),t=this.encodePoint(n),r=this.hashInt(t,r.pubBytes(),e).mul(r.priv()),r=i.add(r).umod(this.curve.n);return this.makeSignature({R:n,S:r,Rencoded:t})},f.prototype.verify=function(e,t,r){e=s(e),t=this.makeSignature(t);var i=this.keyFromPublic(r),r=this.hashInt(t.Rencoded(),i.pubBytes(),e),e=this.g.mul(t.S());return t.R().add(i.pub().mul(r)).eq(e)},f.prototype.hashInt=function(){for(var e=this.hash(),t=0;t>1)-1>1)-u:u,a.isubn(s)):s=0,i[o]=s,a.iushrn(1)}return i},i.getJSF=function(e,t){var r=[[],[]];e=e.clone(),t=t.clone();for(var i=0,n=0;0r&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},i.prototype.once=function(e,t){if(!u(t))throw TypeError("listener must be a function");var r=!1;function i(){this.removeListener(e,i),r||(r=!0,t.apply(this,arguments))}return i.listener=t,this.on(e,i),this},i.prototype.removeListener=function(e,t){var r,i,n,a;if(!u(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(n=(r=this._events[e]).length,i=-1,r===t||u(r.listener)&&r.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(c(r)){for(a=n;0=this._blockSize;){for(var n=this._blockOffset;n=this._delta8){t=(e=this.pending).length%this._delta8;this.pending=e.slice(e.length-t,e.length),0===this.pending.length&&(this.pending=null),e=i.join32(e,0,e.length-t,this.endian);for(var r=0;r>>24&255,i[n++]=e>>>16&255,i[n++]=e>>>8&255,i[n++]=255&e}else for(i[n++]=255&e,i[n++]=e>>>8&255,i[n++]=e>>>16&255,i[n++]=e>>>24&255,i[n++]=0,i[n++]=0,i[n++]=0,i[n++]=0,a=8;athis.blockSize&&(e=(new this.Hash).update(e).digest()),n(e.length<=this.blockSize);for(var t=e.length;t>>3},r.g1_256=function(e){return i(e,17)^i(e,19)^e>>>10}},{"../utils":286}],286:[function(e,t,r){"use strict";var u=e("minimalistic-assert"),e=e("inherits");function a(e){return(e>>>24|e>>>8&65280|e<<8&16711680|(255&e)<<24)>>>0}function i(e){return 1===e.length?"0"+e:e}function o(e){return 7===e.length?"0"+e:6===e.length?"00"+e:5===e.length?"000"+e:4===e.length?"0000"+e:3===e.length?"00000"+e:2===e.length?"000000"+e:1===e.length?"0000000"+e:e}r.inherits=e,r.toArray=function(e,t){if(Array.isArray(e))return e.slice();if(!e)return[];var r,i,n=[];if("string"==typeof e)if(t){if("hex"===t)for((e=e.replace(/[^a-z0-9]+/gi,"")).length%2!=0&&(e="0"+e),o=0;o>6|192,n[a++]=63&s|128):(i=o,55296!=(64512&(r=e).charCodeAt(i))||i<0||i+1>=r.length||56320!=(64512&r.charCodeAt(i+1))?n[a++]=s>>12|224:(s=65536+((1023&s)<<10)+(1023&e.charCodeAt(++o)),n[a++]=s>>18|240,n[a++]=s>>12&63|128),n[a++]=s>>6&63|128,n[a++]=63&s|128)}else for(o=0;o>>0}return n},r.split32=function(e,t){for(var r=new Array(4*e.length),i=0,n=0;i>>24,r[n+1]=a>>>16&255,r[n+2]=a>>>8&255,r[n+3]=255&a):(r[n+3]=a>>>24,r[n+2]=a>>>16&255,r[n+1]=a>>>8&255,r[n]=255&a)}return r},r.rotr32=function(e,t){return e>>>t|e<<32-t},r.rotl32=function(e,t){return e<>>32-t},r.sum32=function(e,t){return e+t>>>0},r.sum32_3=function(e,t,r){return e+t+r>>>0},r.sum32_4=function(e,t,r,i){return e+t+r+i>>>0},r.sum32_5=function(e,t,r,i,n){return e+t+r+i+n>>>0},r.sum64=function(e,t,r,i){var n=e[t],a=i+e[t+1]>>>0,n=(a>>0,e[t+1]=a},r.sum64_hi=function(e,t,r,i){return(t+i>>>0>>0},r.sum64_lo=function(e,t,r,i){return t+i>>>0},r.sum64_4_hi=function(e,t,r,i,n,a,o,s){var u=0,c=t;return u+=(c=c+i>>>0)>>0)>>0)>>0},r.sum64_4_lo=function(e,t,r,i,n,a,o,s){return t+i+a+s>>>0},r.sum64_5_hi=function(e,t,r,i,n,a,o,s,u,c){var f=0,p=t;return f+=(p=p+i>>>0)>>0)>>0)>>0)>>0},r.sum64_5_lo=function(e,t,r,i,n,a,o,s,u,c){return t+i+a+s+c>>>0},r.rotr64_hi=function(e,t,r){return(t<<32-r|e>>>r)>>>0},r.rotr64_lo=function(e,t,r){return(e<<32-r|t>>>r)>>>0},r.shr64_hi=function(e,t,r){return e>>>r},r.shr64_lo=function(e,t,r){return(e<<32-r|t>>>r)>>>0}},{inherits:287,"minimalistic-assert":324}],287:[function(e,t,r){arguments[4][162][0].apply(r,arguments)},{dup:162}],288:[function(e,t,r){"use strict";var i=e("hash.js"),a=e("minimalistic-crypto-utils"),n=e("minimalistic-assert");function o(e){if(!(this instanceof o))return new o(e);this.hash=e.hash,this.predResist=!!e.predResist,this.outLen=this.hash.outSize,this.minEntropy=e.minEntropy||this.hash.hmacStrength,this._reseed=null,this.reseedInterval=null,this.K=null,this.V=null;var t=a.toArray(e.entropy,e.entropyEnc||"hex"),r=a.toArray(e.nonce,e.nonceEnc||"hex"),e=a.toArray(e.pers,e.persEnc||"hex");n(t.length>=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._init(t,r,e)}(t.exports=o).prototype._init=function(e,t,r){r=e.concat(t).concat(r);this.K=new Array(this.outLen/8),this.V=new Array(this.outLen/8);for(var i=0;i=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._update(e.concat(r||[])),this._reseed=1},o.prototype.generate=function(e,t,r,i){if(this._reseed>this.reseedInterval)throw new Error("Reseed is required");"string"!=typeof t&&(i=r,r=t,t=null),r&&(r=a.toArray(r,i||"hex"),this._update(r));for(var n=[];n.length1e3*t.clockSkew)throw new S("clock skew of "+d/1e3+"s was greater than "+t.clockSkew+"s")}if(t.headers.forEach(function(e){if(u.params.headers.indexOf(e.toLowerCase())<0)throw new A(e+" was not a signed header")}),t.algorithms&&-1===t.algorithms.indexOf(u.params.algorithm))throw new E(u.params.algorithm+" is not a supported algorithm");return u.algorithm=u.params.algorithm.toUpperCase(),u.keyId=u.params.keyId,u}}},{"./utils":292,"assert-plus":67,util:481}],291:[function(n,a,e){(function(k){(function(){var f=n("assert-plus"),p=n("crypto"),e=(n("http"),n("util")),l=n("sshpk"),h=n("jsprim"),t=n("./utils"),d=n("util").format,m=t.HASH_ALGOS,g=t.PK_ALGOS,b=t.InvalidAlgorithmError,r=t.HttpSignatureError,y=t.validateAlgorithm,v='Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"';function _(e){r.call(this,e,_)}function w(e){r.call(this,e,w)}function i(e){f.object(e,"options");var t=[];if(void 0!==e.algorithm&&(f.string(e.algorithm,"options.algorithm"),t=y(e.algorithm)),this.rs_alg=t,void 0!==e.sign)f.func(e.sign,"options.sign"),this.rs_signFunc=e.sign;else if("hmac"===t[0]&&void 0!==e.key){if(f.string(e.keyId,"options.keyId"),this.rs_keyId=e.keyId,"string"!=typeof e.key&&!k.isBuffer(e.key))throw new TypeError("options.key for HMAC must be a string or Buffer");this.rs_signer=p.createHmac(t[1].toUpperCase(),e.key),this.rs_signer.sign=function(){var e=this.digest("base64");return{hashAlgorithm:t[1],toString:function(){return e}}}}else{if(void 0===e.key)throw new TypeError("options.sign (func) or options.key is required");var r=e.key;if("string"!=typeof r&&!k.isBuffer(r)||(r=l.parsePrivateKey(r)),f.ok(l.PrivateKey.isPrivateKey(r,[1,2]),"options.key must be a sshpk.PrivateKey"),this.rs_key=r,f.string(e.keyId,"options.keyId"),this.rs_keyId=e.keyId,!g[r.type])throw new b(r.type.toUpperCase()+" type keys are not supported");if(void 0!==t[0]&&r.type!==t[0])throw new b("options.key must be a "+t[0].toUpperCase()+" key, was given a "+r.type.toUpperCase()+" key instead");this.rs_signer=r.createSign(t[1])}this.rs_headers=[],this.rs_lines=[]}e.inherits(_,r),e.inherits(w,r),i.prototype.writeHeader=function(e,t){return f.string(e,"header"),e=e.toLowerCase(),f.string(t,"value"),this.rs_headers.push(e),this.rs_signFunc?this.rs_lines.push(e+": "+t):(e=e+": "+t,0>1,f=-7,p=r?n-1:0,l=r?-1:1,r=e[t+p];for(p+=l,a=r&(1<<-f)-1,r>>=-f,f+=s;0>=-f,f+=i;0>1,p=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,l=i?0:a-1,h=i?1:-1,a=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=c):(o=Math.floor(Math.log(t)/Math.LN2),t*(i=Math.pow(2,-o))<1&&(o--,i*=2),2<=(t+=1<=o+f?p/i:p*Math.pow(2,1-f))*i&&(o++,i/=2),c<=o+f?(s=0,o=c):1<=o+f?(s=(t*i-1)*Math.pow(2,n),o+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,n),o=0));8<=n;e[r+l]=255&s,l+=h,s/=256,n-=8);for(o=o<>15;0<=--a;){var u=32767&this[e],c=this[e++]>>15,f=s*u+c*o;n=((u=o*u+((32767&f)<<15)+r[i]+(1073741823&n))>>>30)+(f>>>15)+s*c+(n>>>30),r[i++]=1073741823&u}return n},30):e&&"Netscape"!=navigator.appName?(b.prototype.am=function(e,t,r,i,n,a){for(;0<=--a;){var o=t*this[e++]+r[i]+n;n=Math.floor(o/67108864),r[i++]=67108863&o}return n},26):(b.prototype.am=function(e,t,r,i,n,a){for(var o=16383&t,s=t>>14;0<=--a;){var u=16383&this[e],c=this[e++]>>14,f=s*u+c*o;n=((u=o*u+((16383&f)<<14)+r[i]+n)>>28)+(f>>14)+s*c,r[i++]=268435455&u}return n},28);b.prototype.DB=e,b.prototype.DM=(1<>>16)&&(e=t,r+=16),0!=(t=e>>8)&&(e=t,r+=8),0!=(t=e>>4)&&(e=t,r+=4),0!=(t=e>>2)&&(e=t,r+=2),0!=(t=e>>1)&&(e=t,r+=1),r}function _(e){this.m=e}function w(e){this.m=e,this.mp=e.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<>15)*this.mpl&this.um)<<15)&e.DM;for(e[r=t+this.m.t]+=this.m.am(0,i,e,t,0,this.m.t);e[r]>=e.DV;)e[r]-=e.DV,e[++r]++}e.clamp(),e.drShiftTo(this.m.t,e),0<=e.compareTo(this.m)&&e.subTo(this.m,e)},w.prototype.mulTo=function(e,t,r){e.multiplyTo(t,r),this.reduce(r)},w.prototype.sqrTo=function(e,t){e.squareTo(t),this.reduce(t)},b.prototype.copyTo=function(e){for(var t=this.t-1;0<=t;--t)e[t]=this[t];e.t=this.t,e.s=this.s},b.prototype.fromInt=function(e){this.t=1,this.s=e<0?-1:0,0this.DB?(this[this.t-1]|=(o&(1<>this.DB-a):this[this.t-1]|=o<=this.DB&&(a-=this.DB))}8==r&&0!=(128&e[0])&&(this.s=-1,0>i|o,o=(this[s]&n)<=this.t)t.t=0;else{var i=e%this.DB,n=this.DB-i,a=(1<>i;for(var o=r+1;o>i;0>=this.DB;if(e.t>=this.DB;i+=this.s}else{for(i+=this.s;r>=this.DB;i-=e.s}t.s=i<0?-1:0,i<-1?t[r++]=this.DV+i:0=t.DV&&(e[r+t.t]-=t.DV,e[r+t.t+1]=1)}0>this.F2:0),f=this.FV/n,p=(1<>s)&&(n=!0,a=u(r));0<=o;)s>(s+=this.DB-t)):(r=this[o]>>(s-=t)&i,s<=0&&(s+=this.DB,--o)),(n=02*this.m.t)return e.mod(this.m);if(e.compareTo(this.m)<0)return e;var t=y();return e.copyTo(t),this.reduce(t),t},k.prototype.revert=function(e){return e},k.prototype.reduce=function(e){for(e.drShiftTo(this.m.t-1,this.r2),e.t>this.m.t+1&&(e.t=this.m.t+1,e.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);e.compareTo(this.r2)<0;)e.dAddOffset(1,this.m.t+1);for(e.subTo(this.r2,e);0<=e.compareTo(this.m);)e.subTo(this.m,e)},k.prototype.mulTo=function(e,t,r){e.multiplyTo(t,r),this.reduce(r)},k.prototype.sqrTo=function(e,t){e.squareTo(t),this.reduce(t)};var h,d=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],m=(1<<26)/d[d.length-1];function x(){var e;e=(new Date).getTime(),S[j++]^=255&e,S[j++]^=e>>8&255,S[j++]^=e>>16&255,S[j++]^=e>>24&255,C<=j&&(j-=C)}if(b.prototype.chunkSize=function(e){return Math.floor(Math.LN2*this.DB/Math.log(e))},b.prototype.toRadix=function(e){if(null==e&&(e=10),0==this.signum()||e<2||36=r&&(this.dMultiply(i),this.dAddOffset(o,0),o=a=0))}0e&&this.subTo(b.ONE.shiftLeft(e-1),this);else{var i=new Array,r=7&e;i.length=1+(e>>3),t.nextBytes(i),0>=this.DB;if(e.t>=this.DB;i+=this.s}else{for(i+=this.s;r>=this.DB;i+=e.s}t.s=i<0?-1:0,0=this.DV;)this[t]-=this.DV,++t>=this.t&&(this[this.t++]=0),++this[t]}},b.prototype.multiplyLowerTo=function(e,t,r){var i,n=Math.min(this.t+e.t,t);for(r.s=0,r.t=n;0>1)>d.length&&(e=d.length);for(var n=y(),a=0;a>24},b.prototype.shortValue=function(){return 0==this.t?this.s:this[0]<<16>>16},b.prototype.signum=function(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1},b.prototype.toByteArray=function(){var e=this.t,t=new Array;t[0]=this.s;var r,i=this.DB-e*this.DB%8,n=0;if(0>i)!=(this.s&this.DM)>>i&&(t[n++]=r|this.s<>(i+=this.DB-8)):(r=this[e]>>(i-=8)&255,i<=0&&(i+=this.DB,--e)),0!=(128&r)&&(r|=-256),0==n&&(128&this.s)!=(128&r)&&++n,(0>=16,t+=16),0==(255&e)&&(e>>=8,t+=8),0==(15&e)&&(e>>=4,t+=4),0==(3&e)&&(e>>=2,t+=2),0==(1&e)&&++t,t}(this[e]);return this.s<0?this.t*this.DB:-1},b.prototype.bitCount=function(){for(var e=0,t=this.s&this.DM,r=0;r=this.t?0!=this.s:0!=(this[t]&1<>n-u&c:(p=(e[h]&(1<>this.DB+n-u)),s=r;0==(1&p);)p>>=1,--s;if((n-=s)<0&&(n+=this.DB,--h),d)o[p].copyTo(a),d=!1;else{for(;1>>8,S[j++]=255&P;j=0,x()}function I(){if(null==h){for(x(),(h=new O).init(S),j=0;jt.maxItems&&i("There must be a maximum of "+t.maxItems+" in the array")}else(t.properties||t.additionalProperties)&&m.concat(function(e,t,r,i){if("object"==_typeof(t))for(var n in("object"!=_typeof(e)||e instanceof Array)&&m.push({property:r,message:"an object is required"}),t){var a,o;t.hasOwnProperty(n)&&(void 0===(a=e[n])&&l.existingOnly||(o=t[n],void 0===a&&o.default&&(a=e[n]=o.default),g(a=l.coerce&&n in e?e[n]=l.coerce(a,o):a,o,r,n)))}for(n in e){if(e.hasOwnProperty(n)&&("_"!=n.charAt(0)||"_"!=n.charAt(1))&&t&&!t[n]&&!1===i){if(l.filter){delete e[n];continue}m.push({property:r,message:_typeof(a)+"The property "+n+" is not defined in the schema and the schema does not allow additional properties"})}var s=t&&t[n]&&t[n].requires;!s||s in e||m.push({property:r,message:"the presence of the property "+n+" requires that "+s+" also be present"}),a=e[n],!i||t&&"object"==_typeof(t)&&n in t||g(a=l.coerce?e[n]=l.coerce(a,i):a,i,r,n),!h&&a&&a.$schema&&(m=m.concat(g(a,a.$schema,r,n)))}return m}(e,t.properties,o,t.additionalProperties));if(t.pattern&&"string"==typeof e&&!e.match(t.pattern)&&i("does not match the regex pattern "+t.pattern),t.maxLength&&"string"==typeof e&&e.length>t.maxLength&&i("may only be "+t.maxLength+" characters long"),t.minLength&&"string"==typeof e&&e.lengthe&&i("must have a minimum value of "+t.minimum),void 0!==_typeof(t.maximum)&&_typeof(e)==_typeof(t.maximum)&&t.maximum= 2"),f.ok(n.base<=36,"options.base <= 36"),f.bool(n.allowSign,"options.allowSign"),f.bool(n.allowPrefix,"options.allowPrefix"),f.bool(n.allowTrailing,"options.allowTrailing"),f.bool(n.allowImprecise,"options.allowImprecise"),f.bool(n.trimWhitespace,"options.trimWhitespace"),f.bool(n.leadingZeroIsOctal,"options.leadingZeroIsOctal"),n.leadingZeroIsOctal&&f.ok(!i,'"base" and "leadingZeroIsOctal" are mutually exclusive'));var a=-1,o=n.base,t=1,s=0,u=0,c=e.length;if(n.trimWhitespace)for(;ut[0]||e[0]==t[0]&&e[1]>=t[1],"negative differences not allowed");var r=[e[0]-t[0],0];return e[1]>=t[1]?r[1]=e[1]-t[1]:(r[0]--,r[1]=1e9-(t[1]-e[1])),r}function B(e,t){return c(e),c(t),e[1]+=t[1],1e9<=e[1]&&(e[0]++,e[1]-=1e9),e[0]+=t[0],e}function F(e,t,r){var i,n={};if(r)for(i in r)n[i]=r[i];if(e)for(i in e)n[i]=e[i];if(t)for(i in t)n[i]=t[i];return n}},{"assert-plus":67,extsprintf:232,"json-schema":303,util:481,verror:485}],306:[function(e,t,r){e=e("./_root").Symbol;t.exports=e},{"./_root":311}],307:[function(e,t,r){var i=e("./_Symbol"),n=e("./_getRawTag"),a=e("./_objectToString"),o=i?i.toStringTag:void 0;t.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":(o&&o in Object(e)?n:a)(e)}},{"./_Symbol":306,"./_getRawTag":309,"./_objectToString":310}],308:[function(e,r,t){(function(t){(function(){var e="object"==_typeof(t)&&t&&t.Object===Object&&t;r.exports=e}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],309:[function(e,t,r){var i=e("./_Symbol"),e=Object.prototype,a=e.hasOwnProperty,o=e.toString,s=i?i.toStringTag:void 0;t.exports=function(e){var t=a.call(e,s),r=e[s];try{var i=!(e[s]=void 0)}catch(e){}var n=o.call(e);return i&&(t?e[s]=r:delete e[s]),n}},{"./_Symbol":306}],310:[function(e,t,r){var i=Object.prototype.toString;t.exports=function(e){return i.call(e)}},{}],311:[function(e,t,r){var i=e("./_freeGlobal"),e="object"==("undefined"==typeof self?"undefined":_typeof(self))&&self&&self.Object===Object&&self,e=i||e||Function("return this")();t.exports=e},{"./_freeGlobal":308}],312:[function(e,t,r){var i=Array.isArray;t.exports=i},{}],313:[function(e,t,r){var i=e("./_baseGetTag"),n=e("./isObject");t.exports=function(e){return!!n(e)&&("[object Function]"==(e=i(e))||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e)}},{"./_baseGetTag":307,"./isObject":314}],314:[function(e,t,r){t.exports=function(e){var t=_typeof(e);return null!=e&&("object"==t||"function"==t)}},{}],315:[function(e,t,r){t.exports=function(e){return null!=e&&"object"==_typeof(e)}},{}],316:[function(e,t,r){var i=e("./_baseGetTag"),n=e("./isArray"),a=e("./isObjectLike");t.exports=function(e){return"string"==typeof e||!n(e)&&a(e)&&"[object String]"==i(e)}},{"./_baseGetTag":307,"./isArray":312,"./isObjectLike":315}],317:[function(e,t,r){t.exports=function(e){return void 0===e}},{}],318:[function(e,P,I){(function(A){(function(){(function(){var qa,Ua="Expected a function",Ha="__lodash_hash_undefined__",Ka="__lodash_placeholder__",Va=9007199254740991,$a=NaN,Ga=4294967295,Wa=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],Za="[object Arguments]",Ya="[object Array]",Qa="[object Boolean]",Xa="[object Date]",Ja="[object Error]",eo="[object Function]",to="[object GeneratorFunction]",ro="[object Map]",io="[object Number]",no="[object Object]",ao="[object Promise]",oo="[object RegExp]",so="[object Set]",uo="[object String]",co="[object Symbol]",fo="[object WeakMap]",po="[object ArrayBuffer]",lo="[object DataView]",ho="[object Float32Array]",mo="[object Float64Array]",go="[object Int8Array]",bo="[object Int16Array]",yo="[object Int32Array]",vo="[object Uint8Array]",_o="[object Uint8ClampedArray]",wo="[object Uint16Array]",ko="[object Uint32Array]",xo=/\b__p \+= '';/g,So=/\b(__p \+=) '' \+/g,jo=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Eo=/&(?:amp|lt|gt|quot|#39);/g,Ao=/[&<>"']/g,Po=RegExp(Eo.source),Io=RegExp(Ao.source),To=/<%-([\s\S]+?)%>/g,Oo=/<%([\s\S]+?)%>/g,Co=/<%=([\s\S]+?)%>/g,Ro=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Bo=/^\w*$/,Fo=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Mo=/[\\^$.*+?()[\]{}|]/g,zo=RegExp(Mo.source),No=/^\s+|\s+$/g,Do=/^\s+/,Lo=/\s+$/,qo=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Uo=/\{\n\/\* \[wrapped with (.+)\] \*/,Ho=/,? & /,Ko=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Vo=/\\(\\)?/g,$o=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Go=/\w*$/,Wo=/^[-+]0x[0-9a-f]+$/i,Zo=/^0b[01]+$/i,Yo=/^\[object .+?Constructor\]$/,Qo=/^0o[0-7]+$/i,Xo=/^(?:0|[1-9]\d*)$/,Jo=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,es=/($^)/,ts=/['\n\r\u2028\u2029\\]/g,e="\\ud800-\\udfff",t="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",r="\\u2700-\\u27bf",i="a-z\\xdf-\\xf6\\xf8-\\xff",n="A-Z\\xc0-\\xd6\\xd8-\\xde",a="\\ufe0e\\ufe0f",o="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",s="["+e+"]",u="["+o+"]",c="["+t+"]",f="\\d+",p="["+r+"]",l="["+i+"]",h="[^"+e+o+f+r+i+n+"]",d="\\ud83c[\\udffb-\\udfff]",m="[^"+e+"]",g="(?:\\ud83c[\\udde6-\\uddff]){2}",b="[\\ud800-\\udbff][\\udc00-\\udfff]",y="["+n+"]",v="(?:"+l+"|"+h+")",o="(?:"+y+"|"+h+")",r="(?:['’](?:d|ll|m|re|s|t|ve))?",i="(?:['’](?:D|LL|M|RE|S|T|VE))?",n="(?:"+c+"|"+d+")"+"?",h="["+a+"]?",n=h+n+("(?:\\u200d(?:"+[m,g,b].join("|")+")"+h+n+")*"),p="(?:"+[p,g,b].join("|")+")"+n,s="(?:"+[m+c+"?",c,g,b,s].join("|")+")",rs=RegExp("['’]","g"),is=RegExp(c,"g"),_=RegExp(d+"(?="+d+")|"+s+n,"g"),ns=RegExp([y+"?"+l+"+"+r+"(?="+[u,y,"$"].join("|")+")",o+"+"+i+"(?="+[u,y+v,"$"].join("|")+")",y+"?"+v+"+"+r,y+"+"+i,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",f,p].join("|"),"g"),w=RegExp("[\\u200d"+e+t+a+"]"),as=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,os=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],ss=-1,us={};us[ho]=us[mo]=us[go]=us[bo]=us[yo]=us[vo]=us[_o]=us[wo]=us[ko]=!0,us[Za]=us[Ya]=us[po]=us[Qa]=us[lo]=us[Xa]=us[Ja]=us[eo]=us[ro]=us[io]=us[no]=us[oo]=us[so]=us[uo]=us[fo]=!1;var cs={};cs[Za]=cs[Ya]=cs[po]=cs[lo]=cs[Qa]=cs[Xa]=cs[ho]=cs[mo]=cs[go]=cs[bo]=cs[yo]=cs[ro]=cs[io]=cs[no]=cs[oo]=cs[so]=cs[uo]=cs[co]=cs[vo]=cs[_o]=cs[wo]=cs[ko]=!0,cs[Ja]=cs[eo]=cs[fo]=!1;var k={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},fs=parseFloat,ps=parseInt,t="object"==_typeof(A)&&A&&A.Object===Object&&A,a="object"==("undefined"==typeof self?"undefined":_typeof(self))&&self&&self.Object===Object&&self,ls=t||a||Function("return this")(),a="object"==_typeof(I)&&I&&!I.nodeType&&I,x=a&&"object"==_typeof(P)&&P&&!P.nodeType&&P,hs=x&&x.exports===a,S=hs&&t.process,t=function(){try{var e=x&&x.require&&x.require("util").types;return e?e:S&&S.binding&&S.binding("util")}catch(e){}}(),ds=t&&t.isArrayBuffer,ms=t&&t.isDate,gs=t&&t.isMap,bs=t&&t.isRegExp,ys=t&&t.isSet,vs=t&&t.isTypedArray;function _s(e,t,r){switch(r.length){case 0:return e.call(t);case 1:return e.call(t,r[0]);case 2:return e.call(t,r[0],r[1]);case 3:return e.call(t,r[0],r[1],r[2])}return e.apply(t,r)}function ws(e,t,r,i){for(var n=-1,a=null==e?0:e.length;++n":">",'"':""","'":"'"});function Ys(e){return"\\"+k[e]}function Qs(e){return w.test(e)}function Xs(e){var r=-1,i=Array(e.size);return e.forEach(function(e,t){i[++r]=[t,e]}),i}function Js(t,r){return function(e){return t(r(e))}}function eu(e,t){for(var r=-1,i=e.length,n=0,a=[];++r",""":'"',"'":"'"});var au=function e(t){var x=(t=null==t?ls:au.defaults(ls.Object(),t,au.pick(ls,os))).Array,r=t.Date,i=t.Error,p=t.Function,n=t.Math,m=t.Object,l=t.RegExp,f=t.String,k=t.TypeError,a=x.prototype,o=p.prototype,h=m.prototype,s=t["__core-js_shared__"],u=o.toString,y=h.hasOwnProperty,c=0,d=(Ca=/[^.]+$/.exec(s&&s.keys&&s.keys.IE_PROTO||""))?"Symbol(src)_1."+Ca:"",g=h.toString,b=u.call(m),v=ls._,_=l("^"+u.call(y).replace(Mo,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),w=hs?t.Buffer:qa,S=t.Symbol,j=t.Uint8Array,E=w?w.allocUnsafe:qa,A=Js(m.getPrototypeOf,m),P=m.create,I=h.propertyIsEnumerable,T=a.splice,O=S?S.isConcatSpreadable:qa,C=S?S.iterator:qa,R=S?S.toStringTag:qa,B=function(){try{var e=qr(m,"defineProperty");return e({},"",{}),e}catch(e){}}(),F=t.clearTimeout!==ls.clearTimeout&&t.clearTimeout,M=r&&r.now!==ls.Date.now&&r.now,z=t.setTimeout!==ls.setTimeout&&t.setTimeout,N=n.ceil,D=n.floor,L=m.getOwnPropertySymbols,q=w?w.isBuffer:qa,U=t.isFinite,H=a.join,K=Js(m.keys,m),V=n.max,$=n.min,G=r.now,W=t.parseInt,Z=n.random,Y=a.reverse,Q=qr(t,"DataView"),X=qr(t,"Map"),J=qr(t,"Promise"),ee=qr(t,"Set"),te=qr(t,"WeakMap"),re=qr(m,"create"),ie=te&&new te,ne={},ae=mi(Q),oe=mi(X),se=mi(J),ue=mi(ee),ce=mi(te),fe=S?S.prototype:qa,pe=fe?fe.valueOf:qa,le=fe?fe.toString:qa;function he(e){if(Rn(e)&&!kn(e)&&!(e instanceof ye)){if(e instanceof be)return e;if(y.call(e,"__wrapped__"))return gi(e)}return new be(e)}var de=function(e){if(!Cn(e))return{};if(P)return P(e);me.prototype=e;e=new me;return me.prototype=qa,e};function me(){}function ge(){}function be(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=qa}function ye(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=Ga,this.__views__=[]}function ve(e){var t=-1,r=null==e?0:e.length;for(this.clear();++t>>0,t>>>=0;for(var a=x(n);++i>>1,o=e[a];null!==o&&!Ln(o)&&(r?o<=t:o>>0)?(e=Yn(e))&&("string"==typeof t||null!=t&&!zn(t))&&!(t=zt(t))&&Qs(e)?Zt(iu(e),0,r):e.split(t,r):[]},he.spread=function(r,i){if("function"!=typeof r)throw new k(Ua);return i=null==i?0:V($n(i),0),St(function(e){var t=e[i],e=Zt(e,0,i);return t&&Is(e,t),_s(r,this,e)})},he.tail=function(e){var t=null==e?0:e.length;return t?Ot(e,1,t):[]},he.take=function(e,t,r){return e&&e.length?Ot(e,0,(t=r||t===qa?1:$n(t))<0?0:t):[]},he.takeRight=function(e,t,r){var i=null==e?0:e.length;return i?Ot(e,(t=i-(t=r||t===qa?1:$n(t)))<0?0:t,i):[]},he.takeRightWhile=function(e,t){return e&&e.length?qt(e,Nr(t,3),!1,!0):[]},he.takeWhile=function(e,t){return e&&e.length?qt(e,Nr(t,3)):[]},he.tap=function(e,t){return t(e),e},he.throttle=function(e,t,r){var i=!0,n=!0;if("function"!=typeof e)throw new k(Ua);return Cn(r)&&(i="leading"in r?!!r.leading:i,n="trailing"in r?!!r.trailing:n),cn(e,t,{leading:i,maxWait:t,trailing:n})},he.thru=Ki,he.toArray=Kn,he.toPairs=ga,he.toPairsIn=ba,he.toPath=function(e){return kn(e)?Ps(e,di):Ln(e)?[e]:ir(hi(Yn(e)))},he.toPlainObject=Zn,he.transform=function(e,i,n){var t,r=kn(e),a=r||En(e)||qn(e);return i=Nr(i,4),null==n&&(t=e&&e.constructor,n=a?r?new t:[]:Cn(e)&&In(t)?de(A(e)):{}),(a?ks:We)(e,function(e,t,r){return i(n,e,t,r)}),n},he.unary=function(e){return an(e,1)},he.union=Ci,he.unionBy=Ri,he.unionWith=Bi,he.uniq=function(e){return e&&e.length?Nt(e):[]},he.uniqBy=function(e,t){return e&&e.length?Nt(e,Nr(t,2)):[]},he.uniqWith=function(e,t){return t="function"==typeof t?t:qa,e&&e.length?Nt(e,qa,t):[]},he.unset=function(e,t){return null==e||Dt(e,t)},he.unzip=Fi,he.unzipWith=Mi,he.update=function(e,t,r){return null==e?e:Lt(e,t,$t(r))},he.updateWith=function(e,t,r,i){return i="function"==typeof i?i:qa,null==e?e:Lt(e,t,$t(r),i)},he.values=ya,he.valuesIn=function(e){return null==e?[]:Ks(e,fa(e))},he.without=zi,he.words=Ia,he.wrap=function(e,t){return mn($t(t),e)},he.xor=Ni,he.xorBy=Di,he.xorWith=Li,he.zip=qi,he.zipObject=function(e,t){return Kt(e||[],t||[],Ie)},he.zipObjectDeep=function(e,t){return Kt(e||[],t||[],At)},he.zipWith=Ui,he.entries=ga,he.entriesIn=ba,he.extend=Xn,he.extendWith=Jn,Fa(he,he),he.add=te,he.attempt=Ta,he.camelCase=va,he.capitalize=_a,he.ceil=s,he.clamp=function(e,t,r){return r===qa&&(r=t,t=qa),r!==qa&&(r=(r=Wn(r))==r?r:0),t!==qa&&(t=(t=Wn(t))==t?t:0),Fe(Wn(e),t,r)},he.clone=function(e){return Me(e,4)},he.cloneDeep=function(e){return Me(e,5)},he.cloneDeepWith=function(e,t){return Me(e,5,t="function"==typeof t?t:qa)},he.cloneWith=function(e,t){return Me(e,4,t="function"==typeof t?t:qa)},he.conformsTo=function(e,t){return null==t||ze(e,t,ca(t))},he.deburr=wa,he.defaultTo=function(e,t){return null==e||e!=e?t:e},he.divide=z,he.endsWith=function(e,t,r){e=Yn(e),t=zt(t);var i=e.length,i=r=r===qa?i:Fe($n(r),0,i);return 0<=(r-=t.length)&&e.slice(r,i)==t},he.eq=yn,he.escape=function(e){return(e=Yn(e))&&Io.test(e)?e.replace(Ao,Zs):e},he.escapeRegExp=function(e){return(e=Yn(e))&&zo.test(e)?e.replace(Mo,"\\$&"):e},he.every=function(e,t,r){return(kn(e)?Ss:Ue)(e,Nr(t=r&&Zr(e,t,r)?qa:t,3))},he.find=Gi,he.findIndex=_i,he.findKey=function(e,t){return Rs(e,Nr(t,3),We)},he.findLast=Wi,he.findLastIndex=wi,he.findLastKey=function(e,t){return Rs(e,Nr(t,3),Ze)},he.floor=It,he.forEach=Zi,he.forEachRight=Yi,he.forIn=function(e,t){return null==e?e:$e(e,Nr(t,3),fa)},he.forInRight=function(e,t){return null==e?e:Ge(e,Nr(t,3),fa)},he.forOwn=function(e,t){return e&&We(e,Nr(t,3))},he.forOwnRight=function(e,t){return e&&Ze(e,Nr(t,3))},he.get=na,he.gt=vn,he.gte=_n,he.has=function(e,t){return null!=e&&Vr(e,t,tt)},he.hasIn=aa,he.head=xi,he.identity=Ra,he.includes=function(e,t,r,i){return e=Sn(e)?e:ya(e),r=r&&!i?$n(r):0,i=e.length,r<0&&(r=V(i+r,0)),Dn(e)?r<=i&&-1=$(t=t,r=r)&&e=this.__values__.length;return{done:e,value:e?qa:this.__values__[this.__index__++]}},he.prototype.plant=function(e){for(var t,r=this;r instanceof ge;){var i=gi(r);i.__index__=0,i.__values__=qa,t?n.__wrapped__=i:t=i;var n=i,r=r.__wrapped__}return n.__wrapped__=e,t},he.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof ye){e=e;return(e=(e=this.__actions__.length?new ye(this):e).reverse()).__actions__.push({func:Ki,args:[Oi],thisArg:qa}),new be(e,this.__chain__)}return this.thru(Oi)},he.prototype.toJSON=he.prototype.valueOf=he.prototype.value=function(){return Ut(this.__wrapped__,this.__actions__)},he.prototype.first=he.prototype.head,C&&(he.prototype[C]=function(){return this}),he}();"function"==typeof B&&"object"==_typeof(B.amd)&&B.amd?(ls._=au,B(function(){return au})):x?((x.exports=au)._=au,a._=au):ls._=au}).call(this)}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],319:[function(e,t,r){"use strict";var i=e("inherits"),n=e("hash-base"),a=e("safe-buffer").Buffer,o=new Array(16);function s(){n.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878}function u(e,t){return e<>>32-t}function c(e,t,r,i,n,a,o){return u(e+(t&r|~t&i)+n+a|0,o)+t|0}function f(e,t,r,i,n,a,o){return u(e+(t&i|r&~i)+n+a|0,o)+t|0}function p(e,t,r,i,n,a,o){return u(e+(t^r^i)+n+a|0,o)+t|0}function l(e,t,r,i,n,a,o){return u(e+(r^(t|~i))+n+a|0,o)+t|0}i(s,n),s.prototype._update=function(){for(var e=o,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);var r=c(r=this._a,a=this._b,n=this._c,i=this._d,e[0],3614090360,7),i=c(i,r,a,n,e[1],3905402710,12),n=c(n,i,r,a,e[2],606105819,17),a=c(a,n,i,r,e[3],3250441966,22);r=c(r,a,n,i,e[4],4118548399,7),i=c(i,r,a,n,e[5],1200080426,12),n=c(n,i,r,a,e[6],2821735955,17),a=c(a,n,i,r,e[7],4249261313,22),r=c(r,a,n,i,e[8],1770035416,7),i=c(i,r,a,n,e[9],2336552879,12),n=c(n,i,r,a,e[10],4294925233,17),a=c(a,n,i,r,e[11],2304563134,22),r=c(r,a,n,i,e[12],1804603682,7),i=c(i,r,a,n,e[13],4254626195,12),n=c(n,i,r,a,e[14],2792965006,17),r=f(r,a=c(a,n,i,r,e[15],1236535329,22),n,i,e[1],4129170786,5),i=f(i,r,a,n,e[6],3225465664,9),n=f(n,i,r,a,e[11],643717713,14),a=f(a,n,i,r,e[0],3921069994,20),r=f(r,a,n,i,e[5],3593408605,5),i=f(i,r,a,n,e[10],38016083,9),n=f(n,i,r,a,e[15],3634488961,14),a=f(a,n,i,r,e[4],3889429448,20),r=f(r,a,n,i,e[9],568446438,5),i=f(i,r,a,n,e[14],3275163606,9),n=f(n,i,r,a,e[3],4107603335,14),a=f(a,n,i,r,e[8],1163531501,20),r=f(r,a,n,i,e[13],2850285829,5),i=f(i,r,a,n,e[2],4243563512,9),n=f(n,i,r,a,e[7],1735328473,14),r=p(r,a=f(a,n,i,r,e[12],2368359562,20),n,i,e[5],4294588738,4),i=p(i,r,a,n,e[8],2272392833,11),n=p(n,i,r,a,e[11],1839030562,16),a=p(a,n,i,r,e[14],4259657740,23),r=p(r,a,n,i,e[1],2763975236,4),i=p(i,r,a,n,e[4],1272893353,11),n=p(n,i,r,a,e[7],4139469664,16),a=p(a,n,i,r,e[10],3200236656,23),r=p(r,a,n,i,e[13],681279174,4),i=p(i,r,a,n,e[0],3936430074,11),n=p(n,i,r,a,e[3],3572445317,16),a=p(a,n,i,r,e[6],76029189,23),r=p(r,a,n,i,e[9],3654602809,4),i=p(i,r,a,n,e[12],3873151461,11),n=p(n,i,r,a,e[15],530742520,16),r=l(r,a=p(a,n,i,r,e[2],3299628645,23),n,i,e[0],4096336452,6),i=l(i,r,a,n,e[7],1126891415,10),n=l(n,i,r,a,e[14],2878612391,15),a=l(a,n,i,r,e[5],4237533241,21),r=l(r,a,n,i,e[12],1700485571,6),i=l(i,r,a,n,e[3],2399980690,10),n=l(n,i,r,a,e[10],4293915773,15),a=l(a,n,i,r,e[1],2240044497,21),r=l(r,a,n,i,e[8],1873313359,6),i=l(i,r,a,n,e[15],4264355552,10),n=l(n,i,r,a,e[6],2734768916,15),a=l(a,n,i,r,e[13],1309151649,21),r=l(r,a,n,i,e[4],4149444226,6),i=l(i,r,a,n,e[11],3174756917,10),n=l(n,i,r,a,e[2],718787259,15),a=l(a,n,i,r,e[9],3951481745,21),this._a=this._a+r|0,this._b=this._b+a|0,this._c=this._c+n|0,this._d=this._d+i|0},s.prototype._digest=function(){this._block[this._blockOffset++]=128,56>8,n=255&n;a?r.push(a,n):r.push(n)}return r},r.zero2=i,r.toHex=n,r.encode=function(e,t){return"hex"===t?n(e):e}},{}],326:[function(e,t,r){(t.exports=o).Minimatch=n;var u={sep:"/"};try{u=e("path")}catch(e){}var B=o.GLOBSTAR=n.GLOBSTAR={},i=e("brace-expansion"),F={"!":{open:"(?:(?!(?:",close:"))[^/]*?)"},"?":{open:"(?:",close:")?"},"+":{open:"(?:",close:")+"},"*":{open:"(?:",close:")*"},"@":{open:"(?:",close:")"}},M="[^/]*?",z="().*{}+?[]^$\\!".split("").reduce(function(e,t){return e[t]=!0,e},{});var c=/\/+/;function a(t,r){t=t||{},r=r||{};var i={};return Object.keys(r).forEach(function(e){i[e]=r[e]}),Object.keys(t).forEach(function(e){i[e]=t[e]}),i}function o(e,t,r){if("string"!=typeof t)throw new TypeError("glob pattern string required");return!(!(r=r||{}).nocomment&&"#"===t.charAt(0))&&(""===t.trim()?""===e:new n(t,r).match(e))}function n(e,t){if(!(this instanceof n))return new n(e,t);if("string"!=typeof e)throw new TypeError("glob pattern string required");t=t||{},e=e.trim(),"/"!==u.sep&&(e=e.split(u.sep).join("/")),this.options=t,this.set=[],this.pattern=e,this.regexp=null,this.negate=!1,this.comment=!1,this.empty=!1,this.make()}function s(e,t){if(t=t||(this instanceof n?this.options:{}),void 0===(e=void 0===e?this.pattern:e))throw new TypeError("undefined pattern");return t.nobrace||!e.match(/\{.*\}/)?[e]:i(e)}o.filter=function(i,n){return n=n||{},function(e,t,r){return o(e,i,n)}},o.defaults=function(i){if(!i||!Object.keys(i).length)return o;function e(e,t,r){return n.minimatch(e,t,a(i,r))}var n=o;return e.Minimatch=function(e,t){return new n.Minimatch(e,a(i,t))},e},n.defaults=function(e){return e&&Object.keys(e).length?o.defaults(e).Minimatch:n},n.prototype.debug=function(){},n.prototype.make=function(){if(this._made)return;var e=this.pattern,t=this.options;if(!t.nocomment&&"#"===e.charAt(0))return void(this.comment=!0);if(!e)return void(this.empty=!0);this.parseNegate();e=this.globSet=this.braceExpand();t.debug&&(this.debug=console.error);this.debug(this.pattern,e),e=this.globParts=e.map(function(e){return e.split(c)}),this.debug(this.pattern,e),e=e.map(function(e,t,r){return e.map(this.parse,this)},this),this.debug(this.pattern,e),e=e.filter(function(e){return-1===e.indexOf(!1)}),this.debug(this.pattern,e),this.set=e},n.prototype.parseNegate=function(){var e=this.pattern,t=!1,r=this.options,i=0;if(r.nonegate)return;for(var n=0,a=e.length;n>> no match, partial?",e,p,t,l),p===o)?!0:!1}if("string"==typeof c?(u=i.nocase?f.toLowerCase()===c.toLowerCase():f===c,this.debug("string match",c,f,u)):(u=f.match(c),this.debug("pattern match",c,f,u)),!u)return!1}if(n===o&&a===s)return!0;if(n===o)return r;if(a===s)return n===o-1&&""===e[n];throw new Error("wtf?")}},{"brace-expansion":130,path:345}],327:[function(e,t,r){var a=e("crypto");function o(e,t,r){return a.createHmac(r,e).update(t).digest("base64")}function s(e){return encodeURIComponent(e).replace(/!/g,"%21").replace(/\*/g,"%2A").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/'/g,"%27")}function i(e,t){return t>>16&65535|0,o=0;0!==r;){for(o=2e3>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,i){var n=s,a=i+r;e^=-1;for(var o=i;o>>8^n[255&(e^t[o])];return-1^e}},{}],333:[function(e,t,r){"use strict";var s,p=e("../utils/common"),u=e("./trees"),l=e("./adler32"),h=e("./crc32"),i=e("./messages"),c=0,f=4,d=0,m=-2,g=-1,b=4,n=2,y=8,v=9,a=286,o=30,_=19,w=2*a+1,k=15,x=3,S=258,j=S+x+1,E=42,A=113,P=1,I=2,T=3,O=4;function C(e,t){return e.msg=i[t],t}function R(e){return(e<<1)-(4e.avail_out?e.avail_out:r)&&(p.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function M(e,t){u._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function z(e,t){e.pending_buf[e.pending++]=t}function N(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function D(e,t){var r,i,n=e.max_chain_length,a=e.strstart,o=e.prev_length,s=e.nice_match,u=e.strstart>e.w_size-j?e.strstart-(e.w_size-j):0,c=e.window,f=e.w_mask,p=e.prev,l=e.strstart+S,h=c[a+o-1],d=c[a+o];e.prev_length>=e.good_match&&(n>>=2),s>e.lookahead&&(s=e.lookahead);do{if(c[(r=t)+o]===d&&c[r+o-1]===h&&c[r]===c[a]&&c[++r]===c[a+1]){for(a+=2,r++;c[++a]===c[++r]&&c[++a]===c[++r]&&c[++a]===c[++r]&&c[++a]===c[++r]&&c[++a]===c[++r]&&c[++a]===c[++r]&&c[++a]===c[++r]&&c[++a]===c[++r]&&au&&0!=--n);return o<=e.lookahead?o:e.lookahead}function L(e){var t,r,i,n,a,o,s,u,c,f=e.w_size;do{if(c=e.window_size-e.lookahead-e.strstart,e.strstart>=f+(f-j)){for(p.arraySet(e.window,e.window,f,f,0),e.match_start-=f,e.strstart-=f,e.block_start-=f,r=e.hash_size,t=r;i=e.head[--t],e.head[t]=f<=i?i-f:0,--r;);for(r=f,t=r;i=e.prev[--t],e.prev[t]=f<=i?i-f:0,--r;);c+=f}if(0===e.strm.avail_in)break;if(a=e.strm,o=e.window,s=e.strstart+e.lookahead,u=c,c=void 0,c=a.avail_in,r=0===(c=u=x)for(n=e.strstart-e.insert,e.ins_h=e.window[n],e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x)if(i=u._tr_tally(e,e.strstart-e.match_start,e.match_length-x),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=x){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x&&e.match_length<=e.prev_length){for(n=e.strstart+e.lookahead-x,i=u._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-x),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=n&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(L(e),0===e.lookahead&&t===c)return P;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var i=e.block_start+r;if((0===e.strstart||e.strstart>=i)&&(e.lookahead=e.strstart-i,e.strstart=i,M(e,!1),0===e.strm.avail_out))return P;if(e.strstart-e.block_start>=e.w_size-j&&(M(e,!1),0===e.strm.avail_out))return P}return e.insert=0,t===f?(M(e,!0),0===e.strm.avail_out?T:O):(e.strstart>e.block_start&&(M(e,!1),e.strm.avail_out),P)}),new H(4,4,8,4,q),new H(4,5,16,8,q),new H(4,6,32,32,q),new H(4,4,16,16,U),new H(8,16,32,32,U),new H(8,16,128,128,U),new H(8,32,128,256,U),new H(32,128,258,1024,U),new H(32,258,258,4096,U)],r.deflateInit=function(e,t){return G(e,t,y,15,8,0)},r.deflateInit2=G,r.deflateReset=$,r.deflateResetKeep=V,r.deflateSetHeader=function(e,t){return!e||!e.state||2!==e.state.wrap?m:(e.state.gzhead=t,d)},r.deflate=function(e,t){var r,i,n,a;if(!e||!e.state||5>8&255),z(r,r.gzhead.time>>16&255),z(r,r.gzhead.time>>24&255),z(r,9===r.level?2:2<=r.strategy||r.level<2?4:0),z(r,255&r.gzhead.os),r.gzhead.extra&&r.gzhead.extra.length&&(z(r,255&r.gzhead.extra.length),z(r,r.gzhead.extra.length>>8&255)),r.gzhead.hcrc&&(e.adler=h(e.adler,r.pending_buf,r.pending,0)),r.gzindex=0,r.status=69):(z(r,0),z(r,0),z(r,0),z(r,0),z(r,0),z(r,9===r.level?2:2<=r.strategy||r.level<2?4:0),z(r,3),r.status=A)):(a=y+(r.w_bits-8<<4)<<8,a|=(2<=r.strategy||r.level<2?0:r.level<6?1:6===r.level?2:3)<<6,0!==r.strstart&&(a|=32),a+=31-a%31,r.status=A,N(r,a),0!==r.strstart&&(N(r,e.adler>>>16),N(r,65535&e.adler)),e.adler=1)),69===r.status)if(r.gzhead.extra){for(i=r.pending;r.gzindex<(65535&r.gzhead.extra.length)&&(r.pending!==r.pending_buf_size||(r.gzhead.hcrc&&r.pending>i&&(e.adler=h(e.adler,r.pending_buf,r.pending-i,i)),F(e),i=r.pending,r.pending!==r.pending_buf_size));)z(r,255&r.gzhead.extra[r.gzindex]),r.gzindex++;r.gzhead.hcrc&&r.pending>i&&(e.adler=h(e.adler,r.pending_buf,r.pending-i,i)),r.gzindex===r.gzhead.extra.length&&(r.gzindex=0,r.status=73)}else r.status=73;if(73===r.status)if(r.gzhead.name){i=r.pending;do{if(r.pending===r.pending_buf_size&&(r.gzhead.hcrc&&r.pending>i&&(e.adler=h(e.adler,r.pending_buf,r.pending-i,i)),F(e),i=r.pending,r.pending===r.pending_buf_size)){n=1;break}}while(n=r.gzindexi&&(e.adler=h(e.adler,r.pending_buf,r.pending-i,i)),0===n&&(r.gzindex=0,r.status=91)}else r.status=91;if(91===r.status)if(r.gzhead.comment){i=r.pending;do{if(r.pending===r.pending_buf_size&&(r.gzhead.hcrc&&r.pending>i&&(e.adler=h(e.adler,r.pending_buf,r.pending-i,i)),F(e),i=r.pending,r.pending===r.pending_buf_size)){n=1;break}}while(n=r.gzindexi&&(e.adler=h(e.adler,r.pending_buf,r.pending-i,i)),0===n&&(r.status=103)}else r.status=103;if(103===r.status&&(r.gzhead.hcrc?(r.pending+2>r.pending_buf_size&&F(e),r.pending+2<=r.pending_buf_size&&(z(r,255&e.adler),z(r,e.adler>>8&255),e.adler=0,r.status=A)):r.status=A),0!==r.pending){if(F(e),0===e.avail_out)return r.last_flush=-1,d}else if(0===e.avail_in&&R(t)<=R(o)&&t!==f)return C(e,-5);if(666===r.status&&0!==e.avail_in)return C(e,-5);if(0!==e.avail_in||0!==r.lookahead||t!==c&&666!==r.status){var o=2===r.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(L(e),0===e.lookahead)){if(t===c)return P;break}if(e.match_length=0,r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(M(e,!1),0===e.strm.avail_out))return P}return e.insert=0,t===f?(M(e,!0),0===e.strm.avail_out?T:O):e.last_lit&&(M(e,!1),0===e.strm.avail_out)?P:I}(r,t):3===r.strategy?function(e,t){for(var r,i,n,a,o=e.window;;){if(e.lookahead<=S){if(L(e),e.lookahead<=S&&t===c)return P;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=x&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=x?(r=u._tr_tally(e,1,e.match_length-x),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(M(e,!1),0===e.strm.avail_out))return P}return e.insert=0,t===f?(M(e,!0),0===e.strm.avail_out?T:O):e.last_lit&&(M(e,!1),0===e.strm.avail_out)?P:I}(r,t):s[r.level].func(r,t);if(o!==T&&o!==O||(r.status=666),o===P||o===T)return 0===e.avail_out&&(r.last_flush=-1),d;if(o===I&&(1===t?u._tr_align(r):5!==t&&(u._tr_stored_block(r,0,0,!1),3===t&&(B(r.head),0===r.lookahead&&(r.strstart=0,r.block_start=0,r.insert=0))),F(e),0===e.avail_out))return r.last_flush=-1,d}return t!==f?d:r.wrap<=0?1:(2===r.wrap?(z(r,255&e.adler),z(r,e.adler>>8&255),z(r,e.adler>>16&255),z(r,e.adler>>24&255),z(r,255&e.total_in),z(r,e.total_in>>8&255),z(r,e.total_in>>16&255),z(r,e.total_in>>24&255)):(N(r,e.adler>>>16),N(r,65535&e.adler)),F(e),0=r.w_size&&(0===a&&(B(r.head),r.strstart=0,r.block_start=0,r.insert=0),u=new p.Buf8(r.w_size),p.arraySet(u,t,c-r.w_size,r.w_size,0),t=u,c=r.w_size),o=e.avail_in,s=e.next_in,u=e.input,e.avail_in=c,e.next_in=0,e.input=t,L(r);r.lookahead>=x;){for(i=r.strstart,n=r.lookahead-(x-1);r.ins_h=(r.ins_h<>>=i=r>>>24,k-=i,0===(i=r>>>16&255))h[l++]=65535&r;else{if(!(16&i)){if(0==(64&i)){r=x[(65535&r)+(w&(1<>>=i,k-=i),k<15&&(w+=f[c++]<>>=i=r>>>24,k-=i,!(16&(i=r>>>16&255))){if(0==(64&i)){r=S[(65535&r)+(w&(1<>>=i,k-=i,(i=l-d)>3,w&=(1<<(k-=n<<3))-1,e.next_in=c,e.next_out=l,e.avail_in=c>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function a(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new I.Buf16(320),this.work=new I.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function o(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=N,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new I.Buf32(i),t.distcode=t.distdyn=new I.Buf32(n),t.sane=1,t.back=-1,M):z}function s(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,o(e)):z}function u(e,t){var r,i;return e&&e.state?(i=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15=n.wsize?(I.arraySet(n.window,t,r-n.wsize,n.wsize,0),n.wnext=0,n.whave=n.wsize):(i<(e=n.wsize-n.wnext)&&(e=i),I.arraySet(n.window,t,r-i,e,n.wnext),(i-=e)?(I.arraySet(n.window,t,r-i,i,0),n.wnext=i,n.whave=n.wsize):(n.wnext+=e,n.wnext===n.wsize&&(n.wnext=0),n.whave>>8&255,r.check=O(r.check,A,2,0),f=c=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&c)<<8)+(c>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&c)){e.msg="unknown compression method",r.mode=30;break}if(f-=4,k=8+(15&(c>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<>8&1),512&r.flags&&(A[0]=255&c,A[1]=c>>>8&255,r.check=O(r.check,A,2,0)),f=c=0,r.mode=3;case 3:for(;f<32;){if(0===s)break e;s--,c+=i[a++]<>>8&255,A[2]=c>>>16&255,A[3]=c>>>24&255,r.check=O(r.check,A,4,0)),f=c=0,r.mode=4;case 4:for(;f<16;){if(0===s)break e;s--,c+=i[a++]<>8),512&r.flags&&(A[0]=255&c,A[1]=c>>>8&255,r.check=O(r.check,A,2,0)),f=c=0,r.mode=5;case 5:if(1024&r.flags){for(;f<16;){if(0===s)break e;s--,c+=i[a++]<>>8&255,r.check=O(r.check,A,2,0)),f=c=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&((h=s<(h=r.length)?s:h)&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),I.arraySet(r.head.extra,i,a,h,k)),512&r.flags&&(r.check=O(r.check,i,h,a)),s-=h,a+=h,r.length-=h),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===s)break e;for(h=0;k=i[a+h++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k)),k&&h>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;f<32;){if(0===s)break e;s--,c+=i[a++]<>>=7&f,f-=7&f,r.mode=27;break}for(;f<3;){if(0===s)break e;s--,c+=i[a++]<>>=1)){case 0:r.mode=14;break;case 1:if(!function(e){if(U){var t;for(L=new I.Buf32(512),q=new I.Buf32(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(R(B,e.lens,0,288,L,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;R(F,e.lens,0,32,q,0,e.work,{bits:5}),U=!1}e.lencode=L,e.lenbits=9,e.distcode=q,e.distbits=5}(r),r.mode=20,6!==t)break;c>>>=2,f-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}c>>>=2,f-=2;break;case 14:for(c>>>=7&f,f-=7&f;f<32;){if(0===s)break e;s--,c+=i[a++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&c,f=c=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(h=r.length){if(0===(h=u<(h=s>>=5,f-=5,r.ndist=1+(31&c),c>>>=5,f-=5,r.ncode=4+(15&c),c>>>=4,f-=4,286>>=3,f-=3}for(;r.have<19;)r.lens[P[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},x=R(0,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have>>16&255,y=65535&E,!((g=E>>>24)<=f);){if(0===s)break e;s--,c+=i[a++]<>>=g,f-=g,r.lens[r.have++]=y;else{if(16===y){for(j=g+2;f>>=g,f-=g,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}k=r.lens[r.have-1],h=3+(3&c),c>>>=2,f-=2}else if(17===y){for(j=g+3;f>>=g)),c>>>=3,f-=3}else{for(j=g+7;f>>=g)),c>>>=7,f-=7}if(r.have+h>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;h--;)r.lens[r.have++]=k}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,S={bits:r.lenbits},x=R(B,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},x=R(F,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,x){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=s&&258<=u){e.next_out=o,e.avail_out=u,e.next_in=a,e.avail_in=s,r.hold=c,r.bits=f,C(e,l),o=e.next_out,n=e.output,u=e.avail_out,a=e.next_in,i=e.input,s=e.avail_in,c=r.hold,f=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;b=(E=r.lencode[c&(1<>>16&255,y=65535&E,!((g=E>>>24)<=f);){if(0===s)break e;s--,c+=i[a++]<>v)])>>>16&255,y=65535&E,!(v+(g=E>>>24)<=f);){if(0===s)break e;s--,c+=i[a++]<>>=v,f-=v,r.back+=v}if(c>>>=g,f-=g,r.back+=g,r.length=y,0===b){r.mode=26;break}if(32&b){r.back=-1,r.mode=12;break}if(64&b){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&b,r.mode=22;case 22:if(r.extra){for(j=r.extra;f>>=r.extra,f-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;b=(E=r.distcode[c&(1<>>16&255,y=65535&E,!((g=E>>>24)<=f);){if(0===s)break e;s--,c+=i[a++]<>v)])>>>16&255,y=65535&E,!(v+(g=E>>>24)<=f);){if(0===s)break e;s--,c+=i[a++]<>>=v,f-=v,r.back+=v}if(c>>>=g,f-=g,r.back+=g,64&b){e.msg="invalid distance code",r.mode=30;break}r.offset=y,r.extra=15&b,r.mode=24;case 24:if(r.extra){for(j=r.extra;f>>=r.extra,f-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===u)break e;if(h=l-u,r.offset>h){if(h=r.offset-h,h>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}d=h>r.wnext?(h-=r.wnext,r.wsize-h):r.wnext-h,h>r.length&&(h=r.length),m=r.window}else m=n,d=o-r.offset,h=r.length;for(uh?(m=C[R+o[v]],P[I+o[v]]):(m=96,0),u=1<>S)+(c-=u)]=d<<24|m<<16|g|0,0!==c;);for(u=1<>=1;if(0!==u?(A&=u-1,A+=u):A=0,v++,0==--T[y]){if(y===w)break;y=t[r+o[v]]}if(k>>7)]}function z(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function N(e,t,r){e.bi_valid>h-r?(e.bi_buf|=t<>h-e.bi_valid,e.bi_valid+=r-h):(e.bi_buf|=t<>>=1,r<<=1,0<--t;);return r>>>1}function q(e,t,r){for(var i,n=new Array(b+1),a=0,o=1;o<=b;o++)n[o]=a=a+r[o-1]<<1;for(i=0;i<=t;i++){var s=e[2*i+1];0!==s&&(e[2*i]=L(n[s]++,s))}}function U(e){for(var t=0;t>1;1<=t;t--)V(e,n,t);for(i=s;t=e.heap[1],e.heap[1]=e.heap[e.heap_len--],V(e,n,1),r=e.heap[1],e.heap[--e.heap_max]=t,e.heap[--e.heap_max]=r,n[2*i]=n[2*t]+n[2*r],e.depth[i]=(e.depth[t]>=e.depth[r]?e.depth[t]:e.depth[r])+1,n[2*t+1]=n[2*r+1]=i,e.heap[1]=i++,V(e,n,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e){for(var t,r,i,n,a,o=m.dyn_tree,s=m.max_code,u=m.stat_desc.static_tree,c=m.stat_desc.has_stree,f=m.stat_desc.extra_bits,p=m.stat_desc.extra_base,l=m.stat_desc.max_length,h=0,d=0;d<=b;d++)e.bl_count[d]=0;for(o[2*e.heap[e.heap_max]+1]=0,t=e.heap_max+1;t>=7;a>>=1)if(1&t&&0!==e.dyn_ltree[2*r])return s;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return u;for(r=32;r>>3,(a=e.static_len+3+7>>>3)<=n&&(n=a)):n=a=r+5,r+4<=n&&-1!==t?Q(e,t,r,i):4===e.strategy||a===n?(N(e,2+(i?1:0),3),$(e,j,E)):(N(e,4+(i?1:0),3),function(e,t,r,i){var n;for(N(e,t-257,5),N(e,r-1,5),N(e,i-4,4),n=0;n>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(P[r]+c+1)]++,e.dyn_dtree[2*M(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){N(e,2,3),D(e,m,j),16===(e=e).bi_valid?(z(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}},{"../utils/common":329}],339:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],340:[function(e,t,r){t.exports={"2.16.840.1.101.3.4.1.1":"aes-128-ecb","2.16.840.1.101.3.4.1.2":"aes-128-cbc","2.16.840.1.101.3.4.1.3":"aes-128-ofb","2.16.840.1.101.3.4.1.4":"aes-128-cfb","2.16.840.1.101.3.4.1.21":"aes-192-ecb","2.16.840.1.101.3.4.1.22":"aes-192-cbc","2.16.840.1.101.3.4.1.23":"aes-192-ofb","2.16.840.1.101.3.4.1.24":"aes-192-cfb","2.16.840.1.101.3.4.1.41":"aes-256-ecb","2.16.840.1.101.3.4.1.42":"aes-256-cbc","2.16.840.1.101.3.4.1.43":"aes-256-ofb","2.16.840.1.101.3.4.1.44":"aes-256-cfb"}},{}],341:[function(e,t,r){"use strict";var i=e("asn1.js");r.certificate=e("./certificate");e=i.define("RSAPrivateKey",function(){this.seq().obj(this.key("version").int(),this.key("modulus").int(),this.key("publicExponent").int(),this.key("privateExponent").int(),this.key("prime1").int(),this.key("prime2").int(),this.key("exponent1").int(),this.key("exponent2").int(),this.key("coefficient").int())});r.RSAPrivateKey=e;e=i.define("RSAPublicKey",function(){this.seq().obj(this.key("modulus").int(),this.key("publicExponent").int())});r.RSAPublicKey=e;e=i.define("SubjectPublicKeyInfo",function(){this.seq().obj(this.key("algorithm").use(n),this.key("subjectPublicKey").bitstr())});r.PublicKey=e;var n=i.define("AlgorithmIdentifier",function(){this.seq().obj(this.key("algorithm").objid(),this.key("none").null_().optional(),this.key("curve").objid().optional(),this.key("params").seq().obj(this.key("p").int(),this.key("q").int(),this.key("g").int()).optional())}),e=i.define("PrivateKeyInfo",function(){this.seq().obj(this.key("version").int(),this.key("algorithm").use(n),this.key("subjectPrivateKey").octstr())});r.PrivateKey=e;e=i.define("EncryptedPrivateKeyInfo",function(){this.seq().obj(this.key("algorithm").seq().obj(this.key("id").objid(),this.key("decrypt").seq().obj(this.key("kde").seq().obj(this.key("id").objid(),this.key("kdeparams").seq().obj(this.key("salt").octstr(),this.key("iters").int())),this.key("cipher").seq().obj(this.key("algo").objid(),this.key("iv").octstr()))),this.key("subjectPrivateKey").octstr())});r.EncryptedPrivateKey=e;e=i.define("DSAPrivateKey",function(){this.seq().obj(this.key("version").int(),this.key("p").int(),this.key("q").int(),this.key("g").int(),this.key("pub_key").int(),this.key("priv_key").int())});r.DSAPrivateKey=e,r.DSAparam=i.define("DSAparam",function(){this.int()});e=i.define("ECPrivateKey",function(){this.seq().obj(this.key("version").int(),this.key("privateKey").octstr(),this.key("parameters").optional().explicit(0).use(a),this.key("publicKey").optional().explicit(1).bitstr())});r.ECPrivateKey=e;var a=i.define("ECParameters",function(){this.choice({namedCurve:this.objid()})});r.signature=i.define("signature",function(){this.seq().obj(this.key("r").int(),this.key("s").int())})},{"./certificate":342,"asn1.js":47}],342:[function(e,t,r){"use strict";var e=e("asn1.js"),i=e.define("Time",function(){this.choice({utcTime:this.utctime(),generalTime:this.gentime()})}),n=e.define("AttributeTypeValue",function(){this.seq().obj(this.key("type").objid(),this.key("value").any())}),a=e.define("AlgorithmIdentifier",function(){this.seq().obj(this.key("algorithm").objid(),this.key("parameters").optional(),this.key("curve").objid().optional())}),o=e.define("SubjectPublicKeyInfo",function(){this.seq().obj(this.key("algorithm").use(a),this.key("subjectPublicKey").bitstr())}),s=e.define("RelativeDistinguishedName",function(){this.setof(n)}),u=e.define("RDNSequence",function(){this.seqof(s)}),c=e.define("Name",function(){this.choice({rdnSequence:this.use(u)})}),f=e.define("Validity",function(){this.seq().obj(this.key("notBefore").use(i),this.key("notAfter").use(i))}),p=e.define("Extension",function(){this.seq().obj(this.key("extnID").objid(),this.key("critical").bool().def(!1),this.key("extnValue").octstr())}),l=e.define("TBSCertificate",function(){this.seq().obj(this.key("version").explicit(0).int().optional(),this.key("serialNumber").int(),this.key("signature").use(a),this.key("issuer").use(c),this.key("validity").use(f),this.key("subject").use(c),this.key("subjectPublicKeyInfo").use(o),this.key("issuerUniqueID").implicit(1).bitstr().optional(),this.key("subjectUniqueID").implicit(2).bitstr().optional(),this.key("extensions").explicit(3).seqof(p).optional())}),e=e.define("X509Certificate",function(){this.seq().obj(this.key("tbsCertificate").use(l),this.key("signatureAlgorithm").use(a),this.key("signatureValue").bitstr())});t.exports=e},{"asn1.js":47}],343:[function(e,t,r){var s=/Proc-Type: 4,ENCRYPTED[\n\r]+DEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)[\n\r]+([0-9A-z\n\r+/=]+)[\n\r]+/m,u=/^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----/m,c=/^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----([0-9A-z\n\r+/=]+)-----END \1-----$/m,f=e("evp_bytestokey"),p=e("browserify-aes"),l=e("safe-buffer").Buffer;t.exports=function(e,t){var r,i,n,a=e.toString(),o=a.match(s);return n=o?(r="aes"+o[1],i=l.from(o[2],"hex"),e=l.from(o[3].replace(/[\r\n]/g,""),"base64"),t=f(t,i.slice(0,8),parseInt(o[1],10)).key,o=[],i=p.createDecipheriv(r,t,i),o.push(i.update(e)),o.push(i.final()),l.concat(o)):(n=a.match(c),l.from(n[2].replace(/[\r\n]/g,""),"base64")),{tag:a.match(u)[1],data:n}}},{"browserify-aes":135,evp_bytestokey:230,"safe-buffer":421}],344:[function(e,t,r){var h=e("./asn1"),d=e("./aesid.json"),m=e("./fixProc"),g=e("browserify-aes"),b=e("pbkdf2"),y=e("safe-buffer").Buffer;function i(e){var t;"object"!==_typeof(e)||y.isBuffer(e)||(t=e.passphrase,e=e.key),"string"==typeof e&&(e=y.from(e));var r,i,n,a,o,s,u,c,f,e=m(e,t),p=e.tag,l=e.data;switch(p){case"CERTIFICATE":i=h.certificate.decode(l,"der").tbsCertificate.subjectPublicKeyInfo;case"PUBLIC KEY":switch(r=(i=i||h.PublicKey.decode(l,"der")).algorithm.algorithm.join(".")){case"1.2.840.113549.1.1.1":return h.RSAPublicKey.decode(i.subjectPublicKey.data,"der");case"1.2.840.10045.2.1":return i.subjectPrivateKey=i.subjectPublicKey,{type:"ec",data:i};case"1.2.840.10040.4.1":return i.algorithm.params.pub_key=h.DSAparam.decode(i.subjectPublicKey.data,"der"),{type:"dsa",data:i.algorithm.params};default:throw new Error("unknown key id "+r)}case"ENCRYPTED PRIVATE KEY":l=h.EncryptedPrivateKey.decode(l,"der"),a=t,o=(n=l).algorithm.decrypt.kde.kdeparams.salt,s=parseInt(n.algorithm.decrypt.kde.kdeparams.iters.toString(),10),u=d[n.algorithm.decrypt.cipher.algo.join(".")],c=n.algorithm.decrypt.cipher.iv,f=n.subjectPrivateKey,n=parseInt(u.split("-")[1],10)/8,n=b.pbkdf2Sync(a,o,s,n,"sha1"),n=g.createDecipheriv(u,n,c),(c=[]).push(n.update(f)),c.push(n.final()),l=y.concat(c);case"PRIVATE KEY":switch(r=(i=h.PrivateKey.decode(l,"der")).algorithm.algorithm.join(".")){case"1.2.840.113549.1.1.1":return h.RSAPrivateKey.decode(i.subjectPrivateKey,"der");case"1.2.840.10045.2.1":return{curve:i.algorithm.curve,privateKey:h.ECPrivateKey.decode(i.subjectPrivateKey,"der").privateKey};case"1.2.840.10040.4.1":return i.algorithm.params.priv_key=h.DSAparam.decode(i.subjectPrivateKey,"der"),{type:"dsa",params:i.algorithm.params};default:throw new Error("unknown key id "+r)}case"RSA PUBLIC KEY":return h.RSAPublicKey.decode(l,"der");case"RSA PRIVATE KEY":return h.RSAPrivateKey.decode(l,"der");case"DSA PRIVATE KEY":return{type:"dsa",params:h.DSAPrivateKey.decode(l,"der")};case"EC PRIVATE KEY":return{curve:(l=h.ECPrivateKey.decode(l,"der")).parameters.value,privateKey:l.privateKey};default:throw new Error("unknown key type "+p)}}(t.exports=i).signature=h.signature},{"./aesid.json":340,"./asn1":341,"./fixProc":343,"browserify-aes":135,pbkdf2:346,"safe-buffer":421}],345:[function(e,t,c){(function(o){(function(){function n(e,t){for(var r=0,i=e.length-1;0<=i;i--){var n=e[i];"."===n?e.splice(i,1):".."===n?(e.splice(i,1),r++):r&&(e.splice(i,1),r--)}if(t)for(;r--;)e.unshift("..");return e}function a(e,t){if(e.filter)return e.filter(t);for(var r=[],i=0;ia?t=n(t):t.length "+t+") {","args = new Array(arguments.length + 1);","for (var i = 0; i < arguments.length; i++) {","args[i] = arguments[i];","}","}","return new Promise(function (rs, rj) {","var cb = "+o+";","var res;","switch (argLength) {",r.concat(["extra"]).map(function(e,t){return"case "+t+":res = fn.call("+["self"].concat(r.slice(0,t)).concat("cb").join(",")+");break;"}).join(""),"default:","args[argLength] = cb;","res = fn.apply(self, args);","}","if (res &&",'(typeof res === "object" || typeof res === "function") &&','typeof res.then === "function"',") {rs(res);}","});","};"].join("");return Function(["Promise","fn"],n)(a,e)}(e)};var o="function (err, res) {if (err) { rj(err); } else { rs(res); }}";a.nodeify=function(r){return function(){var e=Array.prototype.slice.call(arguments),t="function"==typeof e[e.length-1]?e.pop():null,i=this;try{return r.apply(this,arguments).nodeify(t,i)}catch(r){if(null==t)return new a(function(e,t){t(r)});n(function(){t.call(i,r)})}}},a.prototype.nodeify=function(t,r){if("function"!=typeof t)return this;this.then(function(e){n(function(){t.call(r,null,e)})},function(e){n(function(){t.call(r,e)})})}},{"./core.js":356,asap:45}],362:[function(e,t,r){"use strict";var i=e("./core.js");(t.exports=i).enableSynchronous=function(){i.prototype.isPending=function(){return 0==this.getState()},i.prototype.isFulfilled=function(){return 1==this.getState()},i.prototype.isRejected=function(){return 2==this.getState()},i.prototype.getValue=function(){if(3===this._65)return this._55.getValue();if(!this.isFulfilled())throw new Error("Cannot get a value of an unfulfilled promise.");return this._55},i.prototype.getReason=function(){if(3===this._65)return this._55.getReason();if(!this.isRejected())throw new Error("Cannot get a rejection reason of a non-rejected promise.");return this._55},i.prototype.getState=function(){return 3===this._65?this._55.getState():-1===this._65||-2===this._65?0:this._65}},i.disableSynchronous=function(){i.prototype.isPending=void 0,i.prototype.isFulfilled=void 0,i.prototype.isRejected=void 0,i.prototype.getValue=void 0,i.prototype.getReason=void 0,i.prototype.getState=void 0}},{"./core.js":356}],363:[function(e,t,r){"use strict";function n(e){for(var t=e.toString(16);4!==t.length;)t="0"+t;return"\\u"+t}t.exports=function(e,t,r,i){return!r.key||61!==t&&58!==t&&t!==r.separator?31a||0<=new c(t).cmp(n.modulus))throw new Error("decryption error");e=r?l(new c(t),n):f(t,n);t=h.alloc(a-e.length),e=h.concat([t,e],a);if(4===i)return function(e,t){var r=e.modulus.byteLength(),i=p("sha1").update(h.alloc(0)).digest(),n=i.length;if(0!==t[0])throw new Error("decryption error");var e=t.slice(1,n+1),t=t.slice(n+1),e=u(e,s(t,n)),a=u(t,s(e,r-n-1));if(function(e,t){e=h.from(e),t=h.from(t);var r=0,i=e.length;e.length!==t.length&&(r++,i=Math.min(e.length,t.length));var n=-1;for(;++n=e.length){n++;break}var a=e.slice(2,i-1);("0002"!==r.toString("hex")&&!t||"0001"!==r.toString("hex")&&t)&&n++;a.length<8&&n++;if(n)throw new Error("decryption error");return e.slice(i)}(e,r);if(3===i)return e;throw new Error("unknown padding")}},{"./mgf":373,"./withPublic":376,"./xor":377,"bn.js":129,"browserify-rsa":153,"create-hash":194,"parse-asn1":344,"safe-buffer":421}],375:[function(e,t,r){var a=e("parse-asn1"),s=e("randombytes"),u=e("create-hash"),c=e("./mgf"),f=e("./xor"),p=e("bn.js"),o=e("./withPublic"),l=e("browserify-rsa"),h=e("safe-buffer").Buffer;t.exports=function(e,t,r){var i,n=e.padding||(r?1:4),e=a(e);if(4===n)i=function(e,t){var r=e.modulus.byteLength(),i=t.length,n=u("sha1").update(h.alloc(0)).digest(),a=n.length,o=2*a;if(r-o-2>6]+u[128|63&n]:n<55296||57344<=n?r+=u[224|n>>12]+u[128|n>>6&63]+u[128|63&n]:(i+=1,n=65536+((1023&n)<<10|1023&t.charCodeAt(i)),r+=u[240|n>>18]+u[128|n>>12&63]+u[128|n>>6&63]+u[128|63&n])}return r},isBuffer:function(e){return null!=e&&!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},merge:o}},{}],383:[function(e,t,r){"use strict";t.exports=function(e,t,r,i){t=t||"&",r=r||"=";var n={};if("string"!=typeof e||0===e.length)return n;var a=/\+/g;e=e.split(t);t=1e3;i&&"number"==typeof i.maxKeys&&(t=i.maxKeys);var o=e.length;0t.highWaterMark&&(t.highWaterMark=(h<=(r=e)?r=h:(r--,r|=r>>>1,r|=r>>>2,r|=r>>>4,r|=r>>>8,r|=r>>>16,r++),r)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0));var r}function m(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(_("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?b.nextTick(g,e):g(e))}function g(e){_("emit readable"),e.emit("readable"),j(e)}function w(e,t){t.readingMore||(t.readingMore=!0,b.nextTick(k,e,t))}function k(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):r=function(e,t,r){var i;ea.length?a.length:e;if(o===a.length?n+=a:n+=a.slice(0,e),0===(e-=o)){o===a.length?(++i,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r).data=a.slice(o);break}++i}return t.length-=i,n}:function(e,t){var r=f.allocUnsafe(e),i=t.head,n=1;i.data.copy(r),e-=i.data.length;for(;i=i.next;){var a=i.data,o=e>a.length?a.length:e;if(a.copy(r,r.length-e,0,o),0===(e-=o)){o===a.length?(++n,i.next?t.head=i.next:t.head=t.tail=null):(t.head=i).data=a.slice(o);break}++n}return t.length-=n,r})(e,t);return i}(e,t.buffer,t.decoder),r);var r}function A(e){var t=e._readableState;if(0=t.highWaterMark||t.ended))return _("read: emitReadable",t.length,t.ended),(0===t.length&&t.ended?A:m)(this),null;if(0===(e=d(e,t))&&t.ended)return 0===t.length&&A(this),null;var i=t.needReadable;return _("need readable",i),(0===t.length||t.length-e>>0),a=this.head,o=0;a;)t=a.data,r=n,i=o,t.copy(r,i),o+=a.data.length,a=a.next;return n},n),i&&i.inspect&&i.inspect.custom&&(t.exports.prototype[i.inspect.custom]=function(){var e=i.inspect({length:this.length});return this.constructor.name+" "+e})},{"safe-buffer":398,util:132}],395:[function(e,t,r){"use strict";var a=e("process-nextick-args");function o(e,t){e.emit("error",t)}t.exports={destroy:function(e,t){var r=this,i=this._readableState&&this._readableState.destroyed,n=this._writableState&&this._writableState.destroyed;return i||n?t?t(e):!e||this._writableState&&this._writableState.errorEmitted||a.nextTick(o,this,e):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(a.nextTick(o,r,e),r._writableState&&(r._writableState.errorEmitted=!0)):t&&t(e)})),this},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},{"process-nextick-args":353}],396:[function(e,t,r){arguments[4][176][0].apply(r,arguments)},{dup:176,events:229}],397:[function(e,t,r){arguments[4][162][0].apply(r,arguments)},{dup:162}],398:[function(e,t,r){var i=e("buffer"),n=i.Buffer;function a(e,t){for(var r in e)t[r]=e[r]}function o(e,t,r){return n(e,t,r)}n.from&&n.alloc&&n.allocUnsafe&&n.allocUnsafeSlow?t.exports=i:(a(i,r),r.Buffer=o),a(n,o),o.from=function(e,t,r){if("number"==typeof e)throw new TypeError("Argument must not be a number");return n(e,t,r)},o.alloc=function(e,t,r){if("number"!=typeof e)throw new TypeError("Argument must be a number");e=n(e);return void 0!==t?"string"==typeof r?e.fill(t,r):e.fill(t):e.fill(0),e},o.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return n(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return i.SlowBuffer(e)}},{buffer:186}],399:[function(e,t,r){t.exports=e("./readable").PassThrough},{"./readable":400}],400:[function(e,t,r){(((r=t.exports=e("./lib/_stream_readable.js")).Stream=r).Readable=r).Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":389,"./lib/_stream_passthrough.js":390,"./lib/_stream_readable.js":391,"./lib/_stream_transform.js":392,"./lib/_stream_writable.js":393}],401:[function(e,t,r){t.exports=e("./readable").Transform},{"./readable":400}],402:[function(e,t,r){t.exports=e("./lib/_stream_writable.js")},{"./lib/_stream_writable.js":393}],403:[function(e,t,r){"use strict";var s=e("../"),u=e("lodash/isArray"),c=e("lodash/isFunction"),f=e("lodash/isObjectLike");t.exports=function(e){var t="Please verify options";if(!f(e))throw new TypeError(t);if(!c(e.request))throw new TypeError(t+".request");if(!u(e.expose)||0===e.expose.length)throw new TypeError(t+".expose");for(var r=s({PromiseImpl:e.PromiseImpl,constructorMixin:e.constructorMixin}),i=e.request.Request.prototype.init,n=!(e.request.Request.prototype.init=function(e){return!f(e)||this._callback||this._rp_promise||r.init.call(this,e),i.apply(this,arguments)}),a=0;a=t.maxRedirects)return r.emit("error",new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+r.uri.href)),!1;t.redirectsFollowed+=1,o.test(i)||(i=a.resolve(r.uri.href,i));var n=r.uri;return r.uri=a.parse(i),r.uri.protocol!==n.protocol&&delete r.agent,t.redirects.push({statusCode:e.statusCode,redirectUri:i}),t.followAllRedirects&&"HEAD"!==r.method&&401!==e.statusCode&&307!==e.statusCode&&(r.method=t.followOriginalHttpMethod?r.method:"GET"),delete r.src,delete r.req,delete r._started,401!==e.statusCode&&307!==e.statusCode&&(delete r.body,delete r._form,r.headers&&(r.removeHeader("host"),r.removeHeader("content-type"),r.removeHeader("content-length"),r.uri.hostname!==r.originalHost.split(":")[0]&&r.removeHeader("authorization"))),t.removeRefererHeader||r.setHeader("referer",n.href),r.emit("redirect"),r.init(),!0},r.Redirect=i},{url:476}],418:[function(e,t,r){"use strict";var u=e("url"),c=e("tunnel-agent"),i=["accept","accept-charset","accept-encoding","accept-language","accept-ranges","cache-control","content-encoding","content-language","content-location","content-md5","content-range","content-type","connection","date","expect","max-forwards","pragma","referer","te","user-agent","via"],f=["proxy-authorization"];function n(e){this.request=e,this.proxyHeaderWhiteList=i,this.proxyHeaderExclusiveList=[],void 0!==e.tunnel&&(this.tunnelOverride=e.tunnel)}n.prototype.isEnabled=function(){var e=this.request;return void 0!==this.tunnelOverride?this.tunnelOverride:"https:"===e.uri.protocol},n.prototype.setup=function(e){var t=this.request;if(e=e||{},"string"==typeof t.proxy&&(t.proxy=u.parse(t.proxy)),!t.proxy||!t.tunnel)return!1;e.proxyHeaderWhiteList&&(this.proxyHeaderWhiteList=e.proxyHeaderWhiteList),e.proxyHeaderExclusiveList&&(this.proxyHeaderExclusiveList=e.proxyHeaderExclusiveList);var r,i,n=this.proxyHeaderExclusiveList.concat(f),a=this.proxyHeaderWhiteList.concat(n),o=(r=t.headers,i=a.reduce(function(e,t){return e[t.toLowerCase()]=!0,e},{}),Object.keys(r).filter(function(e){return i[e.toLowerCase()]}).reduce(function(e,t){return e[t]=r[t],e},{}));o.host=(s=t.uri,e=s.port,a=s.protocol,s=s.hostname+":",s+=e||("https:"===a?"443":"80")),n.forEach(t.removeHeader,t);var s,n=(s=(a=t).uri,a=a=a.proxy,a=["https:"===s.protocol?"https":"http","https:"===a.protocol?"Https":"Http"].join("Over"),c[a]),a=(s=o,{proxy:{host:(o=(a=t).proxy).hostname,port:+o.port,proxyAuth:o.auth,headers:s},headers:a.headers,ca:a.ca,cert:a.cert,key:a.key,passphrase:a.passphrase,pfx:a.pfx,ciphers:a.ciphers,rejectUnauthorized:a.rejectUnauthorized,secureOptions:a.secureOptions,secureProtocol:a.secureProtocol});return t.agent=n(a),!0},n.defaultProxyHeaderWhiteList=i,n.defaultProxyHeaderExclusiveList=f,r.Tunnel=n},{"tunnel-agent":473,url:476}],419:[function(U,H,e){(function(q){(function(){"use strict";var g=U("http"),b=U("https"),y=U("url"),e=U("util"),n=U("stream"),s=U("zlib"),a=U("aws-sign2"),o=U("aws4"),t=U("http-signature"),v=U("mime-types"),_=U("caseless"),w=U("forever-agent"),r=U("form-data"),u=U("extend"),k=U("isstream"),x=U("is-typedarray").strict,i=U("./lib/helpers"),c=U("./lib/cookies"),S=U("./lib/getProxyFromURI"),f=U("./lib/querystring").Querystring,p=U("./lib/har").Har,l=U("./lib/auth").Auth,h=U("./lib/oauth").OAuth,d=U("./lib/hawk"),m=U("./lib/multipart").Multipart,j=U("./lib/redirect").Redirect,E=U("./lib/tunnel").Tunnel,A=U("performance-now"),P=U("safe-buffer").Buffer,I=i.safeStringify,T=i.isReadStream,O=i.toBase64,C=i.defer,R=i.copy,B=i.version,F=c.jar(),M={};function z(){return{uri:this.uri,method:this.method,headers:this.headers}}function N(){return{statusCode:this.statusCode,body:this.body,headers:this.headers,request:z.call(this.request)}}function D(e){var t=this;e.har&&(t._har=new p(t),e=t._har.options(e)),n.Stream.call(t);var r=Object.keys(D.prototype),i=function(e,t){var r,i={};for(r in t)-1===e.indexOf(r)&&(i[r]=t[r]);return i}(r,e);u(t,i),e=function(e,t){var r,i={};for(r in t){var n=!(-1===e.indexOf(r)),a="function"==typeof t[r];n&&a||(i[r]=t[r])}return i}(r,e),t.readable=!0,t.writable=!0,e.method&&(t.explicitMethod=!0),t._qs=new f(t),t._auth=new l(t),t._oauth=new h(t),t._multipart=new m(t),t._redirect=new j(t),t._tunnel=new E(t),t.init(e)}function L(){D.debug&&console.error("REQUEST %s",e.format.apply(e,arguments))}e.inherits(D,n.Stream),D.debug=q.env.NODE_DEBUG&&/\brequest\b/.test(q.env.NODE_DEBUG),D.prototype.debug=L,D.prototype.init=function(e){var t,i=this;for(t in e=e||{},i.headers=i.headers?R(i.headers):{},i.headers)void 0===i.headers[t]&&delete i.headers[t];if(_.httpify(i,i.headers),i.method||(i.method=e.method||"GET"),i.localAddress||(i.localAddress=e.localAddress),i._qs.init(e),L(e),i.pool||!1===i.pool||(i.pool=M),i.dests=i.dests||[],i.__isRequestRequest=!0,!i._callback&&i.callback&&(i._callback=i.callback,i.callback=function(){i._callbackCalled||(i._callbackCalled=!0,i._callback.apply(i,arguments))},i.on("error",i.callback.bind()),i.on("complete",i.callback.bind(i,null))),!i.uri&&i.url&&(i.uri=i.url,delete i.url),i.baseUrl){if("string"!=typeof i.baseUrl)return i.emit("error",new Error("options.baseUrl must be a string"));if("string"!=typeof i.uri)return i.emit("error",new Error("options.uri must be a string when using options.baseUrl"));if(0===i.uri.indexOf("//")||-1!==i.uri.indexOf("://"))return i.emit("error",new Error("options.uri must be a path when using options.baseUrl"));var r=i.baseUrl.lastIndexOf("/")===i.baseUrl.length-1,n=0===i.uri.indexOf("/");r&&n?i.uri=i.baseUrl+i.uri.slice(1):r||n?i.uri=i.baseUrl+i.uri:""===i.uri?i.uri=i.baseUrl:i.uri=i.baseUrl+"/"+i.uri,delete i.baseUrl}if(!i.uri)return i.emit("error",new Error("options.uri is a required argument"));if("string"==typeof i.uri&&(i.uri=y.parse(i.uri)),i.uri.href||(i.uri.href=y.format(i.uri)),"unix:"===i.uri.protocol)return i.emit("error",new Error("`unix://` URL scheme is no longer supported. Please use the format `http://unix:SOCKET:PATH`"));if("unix"===i.uri.host&&i.enableUnixSocket(),!1===i.strictSSL&&(i.rejectUnauthorized=!1),i.uri.pathname||(i.uri.pathname="/"),!(i.uri.host||i.uri.hostname&&i.uri.port||i.uri.isUnix)){var a='Invalid URI "'+y.format(i.uri)+'"';return 0===Object.keys(e).length&&(a+=". This can be caused by a crappy redirection."),i.abort(),i.emit("error",new Error(a))}if(i.hasOwnProperty("proxy")||(i.proxy=S(i.uri)),i.tunnel=i._tunnel.isEnabled(),i.proxy&&i._tunnel.setup(e),i._redirect.onRequest(e),i.setHost=!1,i.hasHeader("host")||(a=i.originalHostHeaderName||"host",i.setHeader(a,i.uri.host),i.uri.port&&("80"===i.uri.port&&"http:"===i.uri.protocol||"443"===i.uri.port&&"https:"===i.uri.protocol)&&i.setHeader(a,i.uri.hostname),i.setHost=!0),i.jar(i._jar||e.jar),i.uri.port||("http:"===i.uri.protocol?i.uri.port=80:"https:"===i.uri.protocol&&(i.uri.port=443)),i.proxy&&!i.tunnel?(i.port=i.proxy.port,i.host=i.proxy.hostname):(i.port=i.uri.port,i.host=i.uri.hostname),e.form&&i.form(e.form),e.formData){var o,s=e.formData,u=i.form(),c=function(e,t){t&&t.hasOwnProperty("value")&&t.hasOwnProperty("options")?u.append(e,t.value,t.options):u.append(e,t)};for(o in s)if(s.hasOwnProperty(o)){var f=s[o];if(f instanceof Array)for(var p=0;p>>32-t}function S(e,t,r,i,n,a,o,s){return x(e+(t^r^i)+a+o|0,s)+n|0}function j(e,t,r,i,n,a,o,s){return x(e+(t&r|~t&i)+a+o|0,s)+n|0}function E(e,t,r,i,n,a,o,s){return x(e+((t|~r)^i)+a+o|0,s)+n|0}function A(e,t,r,i,n,a,o,s){return x(e+(t&i|r&~i)+a+o|0,s)+n|0}function P(e,t,r,i,n,a,o,s){return x(e+(t^(r|~i))+a+o|0,s)+n|0}n(o,a),o.prototype._update=function(){for(var e=g,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);for(var r=0|this._a,i=0|this._b,n=0|this._c,a=0|this._d,o=0|this._e,s=0|this._a,u=0|this._b,c=0|this._c,f=0|this._d,p=0|this._e,l=0;l<80;l+=1)var h,d=l<16?(h=S(r,i,n,a,o,e[b[l]],w[0],v[l]),P(s,u,c,f,p,e[y[l]],k[0],_[l])):l<32?(h=j(r,i,n,a,o,e[b[l]],w[1],v[l]),A(s,u,c,f,p,e[y[l]],k[1],_[l])):l<48?(h=E(r,i,n,a,o,e[b[l]],w[2],v[l]),E(s,u,c,f,p,e[y[l]],k[2],_[l])):l<64?(h=A(r,i,n,a,o,e[b[l]],w[3],v[l]),j(s,u,c,f,p,e[y[l]],k[3],_[l])):(h=P(r,i,n,a,o,e[b[l]],w[4],v[l]),S(s,u,c,f,p,e[y[l]],k[4],_[l])),r=o,o=a,a=x(n,10),n=i,i=h,s=p,p=f,f=x(c,10),c=u,u=d;var m=this._b+n+f|0;this._b=this._c+a+p|0,this._c=this._d+o+s|0,this._d=this._e+r+u|0,this._e=this._a+i+c|0,this._a=m},o.prototype._digest=function(){this._block[this._blockOffset++]=128,56=this._finalSize&&(this._update(this._block),this._block.fill(0));t=8*this._len;t<=4294967295?this._block.writeUInt32BE(t,this._blockSize-4):(t=(t-(r=(4294967295&t)>>>0))/4294967296,this._block.writeUInt32BE(t,this._blockSize-8),this._block.writeUInt32BE(r,this._blockSize-4)),this._update(this._block);var r=this._hash();return e?r.toString(e):r},i.prototype._update=function(){throw new Error("_update must be implemented by subclass")},t.exports=i},{"safe-buffer":421}],424:[function(e,t,r){(r=t.exports=function(e){e=e.toLowerCase();var t=r[e];if(!t)throw new Error(e+" is not supported (we accept pull requests)");return new t}).sha=e("./sha"),r.sha1=e("./sha1"),r.sha224=e("./sha224"),r.sha256=e("./sha256"),r.sha384=e("./sha384"),r.sha512=e("./sha512")},{"./sha":425,"./sha1":426,"./sha224":427,"./sha256":428,"./sha384":429,"./sha512":430}],425:[function(e,t,r){var i=e("inherits"),n=e("./hash"),a=e("safe-buffer").Buffer,d=[1518500249,1859775393,-1894007588,-899497514],o=new Array(80);function s(){this.init(),this._w=o,n.call(this,64,56)}i(s,n),s.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},s.prototype._update=function(e){for(var t=this._w,r=0|this._a,i=0|this._b,n=0|this._c,a=0|this._d,o=0|this._e,s=0;s<16;++s)t[s]=e.readInt32BE(4*s);for(;s<80;++s)t[s]=t[s-3]^t[s-8]^t[s-14]^t[s-16];for(var u,c,f,p=0;p<80;++p)var l=~~(p/20),h=0|((f=r)<<5|f>>>27)+(u=i,c=n,h=a,0===(f=l)?u&c|~u&h:2===f?u&c|u&h|c&h:u^c^h)+o+t[p]+d[l],o=a,a=n,n=(l=i)<<30|l>>>2,i=r,r=h;this._a=r+this._a|0,this._b=i+this._b|0,this._c=n+this._c|0,this._d=a+this._d|0,this._e=o+this._e|0},s.prototype._hash=function(){var e=a.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},t.exports=s},{"./hash":423,inherits:296,"safe-buffer":421}],426:[function(e,t,r){var i=e("inherits"),n=e("./hash"),a=e("safe-buffer").Buffer,m=[1518500249,1859775393,-1894007588,-899497514],o=new Array(80);function s(){this.init(),this._w=o,n.call(this,64,56)}i(s,n),s.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},s.prototype._update=function(e){for(var t,r=this._w,i=0|this._a,n=0|this._b,a=0|this._c,o=0|this._d,s=0|this._e,u=0;u<16;++u)r[u]=e.readInt32BE(4*u);for(;u<80;++u)r[u]=(t=r[u-3]^r[u-8]^r[u-14]^r[u-16])<<1|t>>>31;for(var c,f,p,l=0;l<80;++l)var h=~~(l/20),d=0|((p=i)<<5|p>>>27)+(c=n,f=a,d=o,0===(p=h)?c&f|~c&d:2===p?c&f|c&d|f&d:c^f^d)+s+r[l]+m[h],s=o,o=a,a=(h=n)<<30|h>>>2,n=i,i=d;this._a=i+this._a|0,this._b=n+this._b|0,this._c=a+this._c|0,this._d=o+this._d|0,this._e=s+this._e|0},s.prototype._hash=function(){var e=a.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},t.exports=s},{"./hash":423,inherits:296,"safe-buffer":421}],427:[function(e,t,r){var i=e("inherits"),n=e("./sha256"),a=e("./hash"),o=e("safe-buffer").Buffer,s=new Array(64);function u(){this.init(),this._w=s,a.call(this,64,56)}i(u,n),u.prototype.init=function(){return this._a=3238371032,this._b=914150663,this._c=812702999,this._d=4144912697,this._e=4290775857,this._f=1750603025,this._g=1694076839,this._h=3204075428,this},u.prototype._hash=function(){var e=o.allocUnsafe(28);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e},t.exports=u},{"./hash":423,"./sha256":428,inherits:296,"safe-buffer":421}],428:[function(e,t,r){var i=e("inherits"),n=e("./hash"),a=e("safe-buffer").Buffer,g=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],o=new Array(64);function s(){this.init(),this._w=o,n.call(this,64,56)}i(s,n),s.prototype.init=function(){return this._a=1779033703,this._b=3144134277,this._c=1013904242,this._d=2773480762,this._e=1359893119,this._f=2600822924,this._g=528734635,this._h=1541459225,this},s.prototype._update=function(e){for(var t,r=this._w,i=0|this._a,n=0|this._b,a=0|this._c,o=0|this._d,s=0|this._e,u=0|this._f,c=0|this._g,f=0|this._h,p=0;p<16;++p)r[p]=e.readInt32BE(4*p);for(;p<64;++p)r[p]=0|(((t=r[p-2])>>>17|t<<15)^(t>>>19|t<<13)^t>>>10)+r[p-7]+(((t=r[p-15])>>>7|t<<25)^(t>>>18|t<<14)^t>>>3)+r[p-16];for(var l,h=0;h<64;++h)var d=f+(((m=s)>>>6|m<<26)^(m>>>11|m<<21)^(m>>>25|m<<7))+((l=c)^s&(u^l))+g[h]+r[h]|0,m=0|(((m=i)>>>2|m<<30)^(m>>>13|m<<19)^(m>>>22|m<<10))+((l=i)&(m=n)|a&(l|m)),f=c,c=u,u=s,s=o+d|0,o=a,a=n,n=i,i=d+m|0;this._a=i+this._a|0,this._b=n+this._b|0,this._c=a+this._c|0,this._d=o+this._d|0,this._e=s+this._e|0,this._f=u+this._f|0,this._g=c+this._g|0,this._h=f+this._h|0},s.prototype._hash=function(){var e=a.allocUnsafe(32);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e.writeInt32BE(this._h,28),e},t.exports=s},{"./hash":423,inherits:296,"safe-buffer":421}],429:[function(e,t,r){var i=e("inherits"),n=e("./sha512"),a=e("./hash"),o=e("safe-buffer").Buffer,s=new Array(160);function u(){this.init(),this._w=s,a.call(this,128,112)}i(u,n),u.prototype.init=function(){return this._ah=3418070365,this._bh=1654270250,this._ch=2438529370,this._dh=355462360,this._eh=1731405415,this._fh=2394180231,this._gh=3675008525,this._hh=1203062813,this._al=3238371032,this._bl=914150663,this._cl=812702999,this._dl=4144912697,this._el=4290775857,this._fl=1750603025,this._gl=1694076839,this._hl=3204075428,this},u.prototype._hash=function(){var i=o.allocUnsafe(48);function e(e,t,r){i.writeInt32BE(e,r),i.writeInt32BE(t,r+4)}return e(this._ah,this._al,0),e(this._bh,this._bl,8),e(this._ch,this._cl,16),e(this._dh,this._dl,24),e(this._eh,this._el,32),e(this._fh,this._fl,40),i},t.exports=u},{"./hash":423,"./sha512":430,inherits:296,"safe-buffer":421}],430:[function(e,t,r){var i=e("inherits"),n=e("./hash"),a=e("safe-buffer").Buffer,D=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591],o=new Array(160);function s(){this.init(),this._w=o,n.call(this,128,112)}function L(e,t,r){return r^e&(t^r)}function q(e,t,r){return e&t|r&(e|t)}function U(e,t){return(e>>>28|t<<4)^(t>>>2|e<<30)^(t>>>7|e<<25)}function H(e,t){return(e>>>14|t<<18)^(e>>>18|t<<14)^(t>>>9|e<<23)}function K(e,t){return e>>>0>>0?1:0}i(s,n),s.prototype.init=function(){return this._ah=1779033703,this._bh=3144134277,this._ch=1013904242,this._dh=2773480762,this._eh=1359893119,this._fh=2600822924,this._gh=528734635,this._hh=1541459225,this._al=4089235720,this._bl=2227873595,this._cl=4271175723,this._dl=1595750129,this._el=2917565137,this._fl=725511199,this._gl=4215389547,this._hl=327033209,this},s.prototype._update=function(e){for(var t=this._w,r=0|this._ah,i=0|this._bh,n=0|this._ch,a=0|this._dh,o=0|this._eh,s=0|this._fh,u=0|this._gh,c=0|this._hh,f=0|this._al,p=0|this._bl,l=0|this._cl,h=0|this._dl,d=0|this._el,m=0|this._fl,g=0|this._gl,b=0|this._hl,y=0;y<32;y+=2)t[y]=e.readInt32BE(4*y),t[y+1]=e.readInt32BE(4*y+4);for(;y<160;y+=2){var v=t[y-30],_=t[y-30+1],w=((E=v)>>>1|(S=_)<<31)^(E>>>8|S<<24)^E>>>7,k=((x=_)>>>1|(j=v)<<31)^(x>>>8|j<<24)^(x>>>7|j<<25),v=t[y-4],_=t[y-4+1],x=((S=v)>>>19|(E=_)<<13)^(E>>>29|S<<3)^S>>>6,S=((j=_)>>>19|(E=v)<<13)^(E>>>29|j<<3)^(j>>>6|E<<26),_=t[y-14],v=t[y-14+1],j=t[y-32],E=t[y-32+1],A=k+v|0,P=w+_+K(A,k)|0;P=(P=P+x+K(A=A+S|0,S)|0)+j+K(A=A+E|0,E)|0,t[y]=P,t[y+1]=A}for(var I=0;I<160;I+=2){P=t[I],A=t[I+1];var T=q(r,i,n),O=q(f,p,l),C=U(r,f),R=U(f,r),B=H(o,d),F=H(d,o),M=D[I+1],z=L(o,s,u),N=L(d,m,g),F=b+F|0,B=c+B+K(F,b)|0;B=(B=(B=B+z+K(F=F+N|0,N)|0)+D[I]+K(F=F+M|0,M)|0)+P+K(F=F+A|0,A)|0;O=R+O|0,R=C+T+K(O,R)|0,c=u,b=g,u=s,g=m,s=o,m=d,o=a+B+K(d=h+F|0,h)|0,a=n,h=l,n=i,l=p,i=r,p=f,r=B+R+K(f=F+O|0,F)|0}this._al=this._al+f|0,this._bl=this._bl+p|0,this._cl=this._cl+l|0,this._dl=this._dl+h|0,this._el=this._el+d|0,this._fl=this._fl+m|0,this._gl=this._gl+g|0,this._hl=this._hl+b|0,this._ah=this._ah+r+K(this._al,f)|0,this._bh=this._bh+i+K(this._bl,p)|0,this._ch=this._ch+n+K(this._cl,l)|0,this._dh=this._dh+a+K(this._dl,h)|0,this._eh=this._eh+o+K(this._el,d)|0,this._fh=this._fh+s+K(this._fl,m)|0,this._gh=this._gh+u+K(this._gl,g)|0,this._hh=this._hh+c+K(this._hl,b)|0},s.prototype._hash=function(){var i=a.allocUnsafe(64);function e(e,t,r){i.writeInt32BE(e,r),i.writeInt32BE(t,r+4)}return e(this._ah,this._al,0),e(this._bh,this._bl,8),e(this._ch,this._cl,16),e(this._dh,this._dl,24),e(this._eh,this._el,32),e(this._fh,this._fl,40),e(this._gh,this._gl,48),e(this._hh,this._hl,56),i},t.exports=s},{"./hash":423,inherits:296,"safe-buffer":421}],431:[function(e,t,r){var i=e("safer-buffer").Buffer,n={dsa:{parts:["p","q","g","y"],sizePart:"p"},rsa:{parts:["e","n"],sizePart:"n"},ecdsa:{parts:["curve","Q"],sizePart:"Q"},ed25519:{parts:["A"],sizePart:"A"}};n.curve25519=n.ed25519;e={dsa:{parts:["p","q","g","y","x"]},rsa:{parts:["n","e","d","iqmp","p","q"]},ecdsa:{parts:["curve","Q","d"]},ed25519:{parts:["A","k"]}};e.curve25519=e.ed25519;i={nistp256:{size:256,pkcs8oid:"1.2.840.10045.3.1.7",p:i.from("00ffffffff 00000001 00000000 0000000000000000 ffffffff ffffffff ffffffff".replace(/ /g,""),"hex"),a:i.from("00FFFFFFFF 00000001 00000000 0000000000000000 FFFFFFFF FFFFFFFF FFFFFFFC".replace(/ /g,""),"hex"),b:i.from("5ac635d8 aa3a93e7 b3ebbd55 769886bc651d06b0 cc53b0f6 3bce3c3e 27d2604b".replace(/ /g,""),"hex"),s:i.from("00c49d3608 86e70493 6a6678e1 139d26b7819f7e90".replace(/ /g,""),"hex"),n:i.from("00ffffffff 00000000 ffffffff ffffffffbce6faad a7179e84 f3b9cac2 fc632551".replace(/ /g,""),"hex"),G:i.from("046b17d1f2 e12c4247 f8bce6e5 63a440f277037d81 2deb33a0 f4a13945 d898c2964fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e162bce3357 6b315ece cbb64068 37bf51f5".replace(/ /g,""),"hex")},nistp384:{size:384,pkcs8oid:"1.3.132.0.34",p:i.from("00ffffffff ffffffff ffffffff ffffffffffffffff ffffffff ffffffff fffffffeffffffff 00000000 00000000 ffffffff".replace(/ /g,""),"hex"),a:i.from("00FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFEFFFFFFFF 00000000 00000000 FFFFFFFC".replace(/ /g,""),"hex"),b:i.from("b3312fa7 e23ee7e4 988e056b e3f82d19181d9c6e fe814112 0314088f 5013875ac656398d 8a2ed19d 2a85c8ed d3ec2aef".replace(/ /g,""),"hex"),s:i.from("00a335926a a319a27a 1d00896a 6773a4827acdac73".replace(/ /g,""),"hex"),n:i.from("00ffffffff ffffffff ffffffff ffffffffffffffff ffffffff c7634d81 f4372ddf581a0db2 48b0a77a ecec196a ccc52973".replace(/ /g,""),"hex"),G:i.from("04aa87ca22 be8b0537 8eb1c71e f320ad746e1d3b62 8ba79b98 59f741e0 82542a385502f25d bf55296c 3a545e38 72760ab73617de4a 96262c6f 5d9e98bf 9292dc29f8f41dbd 289a147c e9da3113 b5f0b8c00a60b1ce 1d7e819d 7a431d7c 90ea0e5f".replace(/ /g,""),"hex")},nistp521:{size:521,pkcs8oid:"1.3.132.0.35",p:i.from("01ffffff ffffffff ffffffff ffffffffffffffff ffffffff ffffffff ffffffffffffffff ffffffff ffffffff ffffffffffffffff ffffffff ffffffff ffffffffffff".replace(/ /g,""),"hex"),a:i.from("01FFFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFC".replace(/ /g,""),"hex"),b:i.from("51953eb961 8e1c9a1f 929a21a0 b68540eea2da725b 99b315f3 b8b48991 8ef109e156193951 ec7e937b 1652c0bd 3bb1bf073573df88 3d2c34f1 ef451fd4 6b503f00".replace(/ /g,""),"hex"),s:i.from("00d09e8800 291cb853 96cc6717 393284aaa0da64ba".replace(/ /g,""),"hex"),n:i.from("01ffffffffff ffffffff ffffffff ffffffffffffffff ffffffff ffffffff fffffffa51868783 bf2f966b 7fcc0148 f709a5d03bb5c9b8 899c47ae bb6fb71e 91386409".replace(/ /g,""),"hex"),G:i.from("0400c6 858e06b7 0404e9cd 9e3ecb66 2395b4429c648139 053fb521 f828af60 6b4d3dbaa14b5e77 efe75928 fe1dc127 a2ffa8de3348b3c1 856a429b f97e7e31 c2e5bd660118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd998f54449 579b4468 17afbd17 273e662c97ee7299 5ef42640 c550b901 3fad0761353c7086 a272c240 88be9476 9fd16650".replace(/ /g,""),"hex")}};t.exports={info:n,privInfo:e,hashAlgs:{md5:!0,sha1:!0,sha256:!0,sha384:!0,sha512:!0},curves:i}},{"safer-buffer":422}],432:[function(e,t,r){t.exports=g;var f=e("assert-plus"),p=e("safer-buffer").Buffer,i=e("./algs"),n=e("crypto"),a=e("./fingerprint"),t=(e("./signature"),e("./errors")),l=(e("util"),e("./utils")),h=e("./key"),d=e("./private-key"),m=e("./identity"),o={};o.openssh=e("./formats/openssh-cert"),o.x509=e("./formats/x509"),o.pem=e("./formats/x509-pem");var s=t.CertificateParseError,u=t.InvalidAlgorithmError;function g(e){f.object(e,"options"),f.arrayOfObject(e.subjects,"options.subjects"),l.assertCompatible(e.subjects[0],m,[1,0],"options.subjects"),l.assertCompatible(e.subjectKey,h,[1,0],"options.subjectKey"),l.assertCompatible(e.issuer,m,[1,0],"options.issuer"),void 0!==e.issuerKey&&l.assertCompatible(e.issuerKey,h,[1,0],"options.issuerKey"),f.object(e.signatures,"options.signatures"),f.buffer(e.serial,"options.serial"),f.date(e.validFrom,"options.validFrom"),f.date(e.validUntil,"optons.validUntil"),f.optionalArrayOfString(e.purposes,"options.purposes"),this._hashCache={},this.subjects=e.subjects,this.issuer=e.issuer,this.subjectKey=e.subjectKey,this.issuerKey=e.issuerKey,this.signatures=e.signatures,this.serial=e.serial,this.validFrom=e.validFrom,this.validUntil=e.validUntil,this.purposes=e.purposes}g.formats=o,g.prototype.toBuffer=function(e,t){return void 0===e&&(e="x509"),f.string(e,"format"),f.object(o[e],"formats[format]"),f.optionalObject(t,"options"),o[e].write(this,t)},g.prototype.toString=function(e,t){return void 0===e&&(e="pem"),this.toBuffer(e,t).toString()},g.prototype.fingerprint=function(e){void 0===e&&(e="sha256"),f.string(e,"algorithm");e={type:"certificate",hash:this.hash(e),algorithm:e};return new a(e)},g.prototype.hash=function(e){if(f.string(e,"algorithm"),e=e.toLowerCase(),void 0===i.hashAlgs[e])throw new u(e);if(this._hashCache[e])return this._hashCache[e];var t=n.createHash(e).update(this.toBuffer("x509")).digest();return this._hashCache[e]=t},g.prototype.isExpired=function(e){return!((e=void 0===e?new Date:e).getTime()>=this.validFrom.getTime()&&e.getTime()e.length||"BEGIN"!==e.slice(t,t+5).toString("ascii"))}(e))return a.read(e,t);if(function(e){var t=0;for(;to.length&&(f=o.length),u+=s.write(o.slice(c,f),u),s[u++]=10,c=f}return u+=s.write("-----END "+i+"-----\n",u),s.slice(0,u)}};var j=e("assert-plus"),E=e("asn1"),A=e("crypto"),P=e("safer-buffer").Buffer,I=(e("../algs"),e("../utils")),p=e("../key"),l=e("../private-key"),T=e("./pkcs1"),O=e("./pkcs8"),C=e("./ssh-private"),R=e("./rfc4253"),B=e("../errors"),F="1.2.840.113549.1.5.13",M="1.2.840.113549.1.5.12",z={"1.2.840.113549.3.7":"3des-cbc","2.16.840.1.101.3.4.1.2":"aes128-cbc","2.16.840.1.101.3.4.1.42":"aes256-cbc"},i={};Object.keys(z).forEach(function(e){i[z[e]]=e});var N={"1.2.840.113549.2.7":"sha1","1.2.840.113549.2.9":"sha256","1.2.840.113549.2.11":"sha512"},n={};Object.keys(N).forEach(function(e){n[N[e]]=e})},{"../algs":431,"../errors":435,"../key":451,"../private-key":452,"../utils":455,"./pkcs1":441,"./pkcs8":442,"./rfc4253":444,"./ssh-private":445,asn1:66,"assert-plus":67,crypto:198,"safer-buffer":422}],441:[function(e,t,r){t.exports={read:function(e,t){return i.read(e,t,"pkcs1")},readPkcs1:function(e,t,r){switch(e){case"RSA":if("public"===t)return function(e){var t=d(e,"modulus"),e=d(e,"exponent");return new l({type:"rsa",parts:[{name:"e",data:e},{name:"n",data:t}]})}(r);if("private"===t)return function(e){var t=d(e,"version");u.strictEqual(t[0],0);var r=d(e,"modulus"),i=d(e,"public exponent"),n=d(e,"private exponent"),a=d(e,"prime1"),o=d(e,"prime2"),s=d(e,"exponent1"),t=d(e,"exponent2"),e=d(e,"iqmp");return new h({type:"rsa",parts:[{name:"n",data:r},{name:"e",data:i},{name:"d",data:n},{name:"iqmp",data:e},{name:"p",data:a},{name:"q",data:o},{name:"dmodp",data:s},{name:"dmodq",data:t}]})}(r);throw new Error("Unknown key type: "+t);case"DSA":if("public"===t)return function(e){var t=d(e,"y"),r=d(e,"p"),i=d(e,"q"),e=d(e,"g");return new l({type:"dsa",parts:[{name:"y",data:t},{name:"p",data:r},{name:"q",data:i},{name:"g",data:e}]})}(r);if("private"===t)return function(e){var t=d(e,"version");u.strictEqual(t.readUInt8(0),0);var r=d(e,"p"),i=d(e,"q"),n=d(e,"g"),t=d(e,"y"),e=d(e,"x");return new h({type:"dsa",parts:[{name:"p",data:r},{name:"q",data:i},{name:"g",data:n},{name:"y",data:t},{name:"x",data:e}]})}(r);throw new Error("Unknown key type: "+t);case"EC":case"ECDSA":if("private"===t)return function(e){var t=d(e,"version");u.strictEqual(t.readUInt8(0),1);var r=e.readString(s.Ber.OctetString,!0);e.readSequence(160);t=n(e);u.string(t,"a known elliptic curve"),e.readSequence(161);e=e.readString(s.Ber.BitString,!0);e=p.ecNormalize(e);r={type:"ecdsa",parts:[{name:"curve",data:c.from(t)},{name:"Q",data:e},{name:"d",data:r}]};return new h(r)}(r);if("public"===t)return function(e){e.readSequence();var t=e.readOID();u.strictEqual(t,"1.2.840.10045.2.1","must be ecPublicKey");for(var r,i=e.readOID(),n=Object.keys(f.curves),a=0;ai.length)throw new Error("Invalid public-lines count");e=c.from(i.slice(a,a+e).join(""),"base64"),o=f.algToKeyType(o),e=f.read(e);if(e.type===o)return e.comment=s,e;throw new Error("Outer key algorithm mismatch")},write:function(e,t){if(u.object(e),!n.isKey(e))throw new Error("Must be a public key");var r=f.keyTypeToAlg(e),i=f.write(e),e=e.comment||"",i=function(e){var t=[],r=0;for(;rb.length&&(_=b.length),y+=g.write(b.slice(v,_),y),g[y++]=10,v=_}return y+=g.write("-----END "+m+"-----\n",y),g.slice(0,y)}};var k,x=w("assert-plus"),S=(w("asn1"),w("safer-buffer").Buffer),j=(w("../algs"),w("../utils")),E=w("crypto"),A=(w("../key"),w("../private-key")),r=w("./pem"),b=w("./rfc4253"),P=w("../ssh-buffer"),y=w("../errors");var I="openssh-key-v1"},{"../algs":431,"../errors":435,"../key":451,"../private-key":452,"../ssh-buffer":454,"../utils":455,"./pem":440,"./rfc4253":444,asn1:66,"assert-plus":67,"bcrypt-pbkdf":77,crypto:198,"safer-buffer":422}],446:[function(e,t,r){t.exports={read:function(t,e){"string"!=typeof t&&(c.buffer(t,"buf"),t=t.toString("ascii"));var r=t.trim().replace(/[\\\r]/g,""),i=r.match(l);i=i||r.match(h);c.ok(i,"key must match regex");var n,a=p.algToKeyType(i[1]),o=f.from(i[2],"base64"),t={};if(i[4])try{n=p.read(o)}catch(e){i=r.match(h),c.ok(i,"key must match regex"),o=f.from(i[2],"base64"),n=p.readInternal(t,"public",o)}else n=p.readInternal(t,"public",o);if(c.strictEqual(a,n.type),i[4]&&0r.length&&(o=r.length),n+=i.write(r.slice(a,o),n),i[n++]=10,a=o}return n+=i.write("-----END "+t+"-----\n",n),i.slice(0,n)}};var c=e("assert-plus"),f=(e("asn1"),e("safer-buffer").Buffer);e("../algs"),e("../utils"),e("../key"),e("../private-key"),e("./pem"),e("../identity"),e("../signature"),e("../certificate")},{"../algs":431,"../certificate":432,"../identity":449,"../key":451,"../private-key":452,"../signature":453,"../utils":455,"./pem":440,"./x509":448,asn1:66,"assert-plus":67,"safer-buffer":422}],448:[function(e,t,r){t.exports={read:function(e,t){"string"==typeof e&&(e=l.from(e,"binary"));p.buffer(e,"buf");var r=new h.BerReader(e);if(r.readSequence(),1=this._buffer.length},a.prototype.remainder=function(){return this._buffer.slice(this._offset)},a.prototype.skip=function(e){this._offset+=e},a.prototype.expand=function(){this._size*=2;var e=n.alloc(this._size);this._buffer.copy(e,0),this._buffer=e},a.prototype.readPart=function(){return{data:this.readBuffer()}},a.prototype.readBuffer=function(){var e=this._buffer.readUInt32BE(this._offset);this._offset+=4,i.ok(this._offset+e<=this._buffer.length,"length out of bounds at +0x"+this._offset.toString(16)+" (data truncated?)");var t=this._buffer.slice(this._offset,this._offset+e);return this._offset+=e,t},a.prototype.readString=function(){return this.readBuffer().toString()},a.prototype.readCString=function(){for(var e=this._offset;ethis._size;)this.expand();this._buffer.writeUInt32BE(e.length,this._offset),this._offset+=4,e.copy(this._buffer,this._offset),this._offset+=e.length},a.prototype.writeString=function(e){this.writeBuffer(n.from(e,"utf8"))},a.prototype.writeCString=function(e){for(;this._offset+1+e.length>this._size;)this.expand();this._buffer.write(e,this._offset),this._offset+=e.length,this._buffer[this._offset++]=0},a.prototype.writeInt=function(e){for(;this._offset+4>this._size;)this.expand();this._buffer.writeUInt32BE(e,this._offset),this._offset+=4},a.prototype.writeInt64=function(e){if(i.buffer(e,"value"),8this._size;)this.expand();e.copy(this._buffer,this._offset),this._offset+=8},a.prototype.writeChar=function(e){for(;this._offset+1>this._size;)this.expand();this._buffer[this._offset++]=e},a.prototype.writePart=function(e){this.writeBuffer(e.data)},a.prototype.write=function(e){for(;this._offset+e.length>this._size;)this.expand();e.copy(this._buffer,this._offset),this._offset+=e.length}},{"assert-plus":67,"safer-buffer":422}],455:[function(e,t,r){t.exports={bufferSplit:function(e,t){f.buffer(e),f.string(t);for(var r=[],i=0,n=0,a=0;a=t.length&&(o=a+1,r.push(e.slice(i,o-n)),i=o,n=0)}i<=e.length&&r.push(e.slice(i,e.length));return r},addRSAMissing:function(e){f.object(e),d(e,n,[1,1]);var t=new c(e.part.d.data);{var r;e.part.dmodp||(r=new c(e.part.p.data),i=t.mod(r.subtract(1)),r=y(i),e.part.dmodp={name:"dmodp",data:r},e.parts.push(e.part.dmodp))}{var i;e.part.dmodq||(i=new c(e.part.q.data),i=t.mod(i.subtract(1)),r=y(i),e.part.dmodq={name:"dmodq",data:r},e.parts.push(e.part.dmodq))}},calculateDSAPublic:function(e,t,r){return f.buffer(e),f.buffer(t),f.buffer(r),e=new c(e),t=new c(t),r=new c(r),y(e.modPow(r,t))},calculateED25519Public:function(e){f.buffer(e);e=i.sign.keyPair.fromSeed(new Uint8Array(e));return p.from(e.publicKey)},calculateX25519Public:function(e){f.buffer(e);e=i.box.keyPair.fromSeed(new Uint8Array(e));return p.from(e.publicKey)},mpNormalize:b,mpDenormalize:function(e){f.buffer(e);for(;1h)return!1;if(i.constructor.name!==t.name)return!1;var a=i._sshpkApiVersion;void 0===a&&(a=t._oldVersionDetect(e));return!(a[0]!=r[0]||a[1]t;)f.equal(e[0],0),e=e.slice(1);for(;e.length=r[1],i+" must be compatible with "+t.name+" klass version "+r[0]+"."+r[1])}}var m={"des-ede3-cbc":{key:24,iv:8},"aes-128-cbc":{key:16,iv:16},"aes-256-cbc":{key:32,iv:16}},g=8;function b(e){for(f.buffer(e);1t._pos){var i=r.substr(t._pos);if("x-user-defined"===t._charset){for(var n=new l(i.length),a=0;at._pos&&(t.push(new l(new Uint8Array(o.result.slice(t._pos)))),t._pos=o.result.byteLength)},o.onload=function(){t.push(null)},o.readAsArrayBuffer(r)}t._xhr.readyState===c.DONE&&"ms-stream"!==t._mode&&t.push(null)}}).call(this)}).call(this,r("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},r("buffer").Buffer)},{"./capability":459,_process:354,buffer:186,inherits:296,"readable-stream":400}],462:[function(e,t,r){"use strict";var i=e("safe-buffer").Buffer,n=i.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function a(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(i.isEncoding===n||!n(e)))throw new Error("Unknown encoding: "+e);return t||e}function o(e){var t;switch(this.encoding=a(e),this.encoding){case"utf16le":this.text=c,this.end=f,t=4;break;case"utf8":this.fillLast=u,t=4;break;case"base64":this.text=p,this.end=l,t=3;break;default:return this.write=h,void(this.end=d)}this.lastNeed=0,this.lastTotal=0,this.lastChar=i.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function u(e){var t,r,i=this.lastTotal-this.lastNeed,t=(t=this,128!=(192&(r=e)[0])?(t.lastNeed=0,"�"):1=this.maxSockets?this.requests.push({host:t.host,port:t.port,request:e}):this.createConnection({host:t.host,port:t.port,request:e})},o.prototype.createConnection=function(e){var n=this;n.createSocket(e,function(t){function r(){n.emit("free",t,e.host,e.port)}function i(e){n.removeSocket(t),t.removeListener("free",r),t.removeListener("close",i),t.removeListener("agentRemove",i)}t.on("free",r),t.on("close",i),t.on("agentRemove",i),e.request.onSocket(t)})},o.prototype.createSocket=function(i,n){var a=this,o={};a.sockets.push(o);var e=l({},a.proxyOptions,{method:"CONNECT",path:i.host+":"+i.port,agent:!1});e.proxyAuth&&(e.headers=e.headers||{},e.headers["Proxy-Authorization"]="Basic "+p.from(e.proxyAuth).toString("base64")),c("making CONNECT request");var s=a.request(e);function u(e,t,r){s.removeAllListeners(),t.removeAllListeners(),200===e.statusCode?(f.equal(r.length,0),c("tunneling connection has established"),a.sockets[a.sockets.indexOf(o)]=t,n(t)):(c("tunneling socket could not be established, statusCode=%d",e.statusCode),(e=new Error("tunneling socket could not be established, statusCode="+e.statusCode)).code="ECONNRESET",i.request.emit("error",e),a.removeSocket(o))}s.useChunkedEncodingByDefault=!1,s.once("response",function(e){e.upgrade=!0}),s.once("upgrade",function(e,t,r){h.nextTick(function(){u(e,t,r)})}),s.once("connect",u),s.once("error",function(e){s.removeAllListeners(),c("tunneling socket could not be established, cause=%s\n",e.message,e.stack);e=new Error("tunneling socket could not be established, cause="+e.message);e.code="ECONNRESET",i.request.emit("error",e),a.removeSocket(o)}),s.end()},o.prototype.removeSocket=function(e){e=this.sockets.indexOf(e);-1!==e&&(this.sockets.splice(e,1),(e=this.requests.shift())&&this.createConnection(e))},c=h.env.NODE_DEBUG&&/\btunnel\b/.test(h.env.NODE_DEBUG)?function(){var e=Array.prototype.slice.call(arguments);"string"==typeof e[0]?e[0]="TUNNEL: "+e[0]:e.unshift("TUNNEL:"),console.error.apply(console,e)}:function(){},u.debug=c}).call(this)}).call(this,s("_process"))},{_process:354,assert:68,events:229,http:458,https:294,net:180,"safe-buffer":421,tls:180,util:481}],474:[function(e,t,r){!function(a){"use strict";var d=function(e){var t,r=new Float64Array(16);if(e)for(t=0;t>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=255&r,e[t+4]=i>>24&255,e[t+5]=i>>16&255,e[t+6]=i>>8&255,e[t+7]=255&i}function g(e,t,r,i,n){for(var a=0,o=0;o>>8)-1}function b(e,t,r,i){return g(e,t,r,i,16)}function y(e,t,r,i){return g(e,t,r,i,32)}function v(e,t,r,i){!function(e,t,r,i){for(var n,a=255&i[0]|(255&i[1])<<8|(255&i[2])<<16|(255&i[3])<<24,o=255&r[0]|(255&r[1])<<8|(255&r[2])<<16|(255&r[3])<<24,s=255&r[4]|(255&r[5])<<8|(255&r[6])<<16|(255&r[7])<<24,u=255&r[8]|(255&r[9])<<8|(255&r[10])<<16|(255&r[11])<<24,c=255&r[12]|(255&r[13])<<8|(255&r[14])<<16|(255&r[15])<<24,f=255&i[4]|(255&i[5])<<8|(255&i[6])<<16|(255&i[7])<<24,p=255&t[0]|(255&t[1])<<8|(255&t[2])<<16|(255&t[3])<<24,l=255&t[4]|(255&t[5])<<8|(255&t[6])<<16|(255&t[7])<<24,h=255&t[8]|(255&t[9])<<8|(255&t[10])<<16|(255&t[11])<<24,d=255&t[12]|(255&t[13])<<8|(255&t[14])<<16|(255&t[15])<<24,m=255&i[8]|(255&i[9])<<8|(255&i[10])<<16|(255&i[11])<<24,g=255&r[16]|(255&r[17])<<8|(255&r[18])<<16|(255&r[19])<<24,b=255&r[20]|(255&r[21])<<8|(255&r[22])<<16|(255&r[23])<<24,t=255&r[24]|(255&r[25])<<8|(255&r[26])<<16|(255&r[27])<<24,r=255&r[28]|(255&r[29])<<8|(255&r[30])<<16|(255&r[31])<<24,i=255&i[12]|(255&i[13])<<8|(255&i[14])<<16|(255&i[15])<<24,y=a,v=o,_=s,w=u,k=c,x=f,S=p,j=l,E=h,A=d,P=m,I=g,T=b,O=t,C=r,R=i,B=0;B<20;B+=2)y^=(n=(T^=(n=(E^=(n=(k^=(n=y+T|0)<<7|n>>>25)+y|0)<<9|n>>>23)+k|0)<<13|n>>>19)+E|0)<<18|n>>>14,x^=(n=(v^=(n=(O^=(n=(A^=(n=x+v|0)<<7|n>>>25)+x|0)<<9|n>>>23)+A|0)<<13|n>>>19)+O|0)<<18|n>>>14,P^=(n=(S^=(n=(_^=(n=(C^=(n=P+S|0)<<7|n>>>25)+P|0)<<9|n>>>23)+C|0)<<13|n>>>19)+_|0)<<18|n>>>14,R^=(n=(I^=(n=(j^=(n=(w^=(n=R+I|0)<<7|n>>>25)+R|0)<<9|n>>>23)+w|0)<<13|n>>>19)+j|0)<<18|n>>>14,y^=(n=(w^=(n=(_^=(n=(v^=(n=y+w|0)<<7|n>>>25)+y|0)<<9|n>>>23)+v|0)<<13|n>>>19)+_|0)<<18|n>>>14,x^=(n=(k^=(n=(j^=(n=(S^=(n=x+k|0)<<7|n>>>25)+x|0)<<9|n>>>23)+S|0)<<13|n>>>19)+j|0)<<18|n>>>14,P^=(n=(A^=(n=(E^=(n=(I^=(n=P+A|0)<<7|n>>>25)+P|0)<<9|n>>>23)+I|0)<<13|n>>>19)+E|0)<<18|n>>>14,R^=(n=(C^=(n=(O^=(n=(T^=(n=R+C|0)<<7|n>>>25)+R|0)<<9|n>>>23)+T|0)<<13|n>>>19)+O|0)<<18|n>>>14;y=y+a|0,v=v+o|0,_=_+s|0,w=w+u|0,k=k+c|0,x=x+f|0,S=S+p|0,j=j+l|0,E=E+h|0,A=A+d|0,P=P+m|0,I=I+g|0,T=T+b|0,O=O+t|0,C=C+r|0,R=R+i|0,e[0]=y>>>0&255,e[1]=y>>>8&255,e[2]=y>>>16&255,e[3]=y>>>24&255,e[4]=v>>>0&255,e[5]=v>>>8&255,e[6]=v>>>16&255,e[7]=v>>>24&255,e[8]=_>>>0&255,e[9]=_>>>8&255,e[10]=_>>>16&255,e[11]=_>>>24&255,e[12]=w>>>0&255,e[13]=w>>>8&255,e[14]=w>>>16&255,e[15]=w>>>24&255,e[16]=k>>>0&255,e[17]=k>>>8&255,e[18]=k>>>16&255,e[19]=k>>>24&255,e[20]=x>>>0&255,e[21]=x>>>8&255,e[22]=x>>>16&255,e[23]=x>>>24&255,e[24]=S>>>0&255,e[25]=S>>>8&255,e[26]=S>>>16&255,e[27]=S>>>24&255,e[28]=j>>>0&255,e[29]=j>>>8&255,e[30]=j>>>16&255,e[31]=j>>>24&255,e[32]=E>>>0&255,e[33]=E>>>8&255,e[34]=E>>>16&255,e[35]=E>>>24&255,e[36]=A>>>0&255,e[37]=A>>>8&255,e[38]=A>>>16&255,e[39]=A>>>24&255,e[40]=P>>>0&255,e[41]=P>>>8&255,e[42]=P>>>16&255,e[43]=P>>>24&255,e[44]=I>>>0&255,e[45]=I>>>8&255,e[46]=I>>>16&255,e[47]=I>>>24&255,e[48]=T>>>0&255,e[49]=T>>>8&255,e[50]=T>>>16&255,e[51]=T>>>24&255,e[52]=O>>>0&255,e[53]=O>>>8&255,e[54]=O>>>16&255,e[55]=O>>>24&255,e[56]=C>>>0&255,e[57]=C>>>8&255,e[58]=C>>>16&255,e[59]=C>>>24&255,e[60]=R>>>0&255,e[61]=R>>>8&255,e[62]=R>>>16&255,e[63]=R>>>24&255}(e,t,r,i)}function _(e,v,_,w){!function(e){for(var t,r=255&w[0]|(255&w[1])<<8|(255&w[2])<<16|(255&w[3])<<24,i=255&_[0]|(255&_[1])<<8|(255&_[2])<<16|(255&_[3])<<24,n=255&_[4]|(255&_[5])<<8|(255&_[6])<<16|(255&_[7])<<24,a=255&_[8]|(255&_[9])<<8|(255&_[10])<<16|(255&_[11])<<24,o=255&_[12]|(255&_[13])<<8|(255&_[14])<<16|(255&_[15])<<24,s=255&w[4]|(255&w[5])<<8|(255&w[6])<<16|(255&w[7])<<24,u=255&v[0]|(255&v[1])<<8|(255&v[2])<<16|(255&v[3])<<24,c=255&v[4]|(255&v[5])<<8|(255&v[6])<<16|(255&v[7])<<24,f=255&v[8]|(255&v[9])<<8|(255&v[10])<<16|(255&v[11])<<24,p=255&v[12]|(255&v[13])<<8|(255&v[14])<<16|(255&v[15])<<24,l=255&w[8]|(255&w[9])<<8|(255&w[10])<<16|(255&w[11])<<24,h=255&_[16]|(255&_[17])<<8|(255&_[18])<<16|(255&_[19])<<24,d=255&_[20]|(255&_[21])<<8|(255&_[22])<<16|(255&_[23])<<24,m=255&_[24]|(255&_[25])<<8|(255&_[26])<<16|(255&_[27])<<24,g=255&_[28]|(255&_[29])<<8|(255&_[30])<<16|(255&_[31])<<24,b=255&w[12]|(255&w[13])<<8|(255&w[14])<<16|(255&w[15])<<24,y=0;y<20;y+=2)r^=(t=(d^=(t=(f^=(t=(o^=(t=r+d|0)<<7|t>>>25)+r|0)<<9|t>>>23)+o|0)<<13|t>>>19)+f|0)<<18|t>>>14,s^=(t=(i^=(t=(m^=(t=(p^=(t=s+i|0)<<7|t>>>25)+s|0)<<9|t>>>23)+p|0)<<13|t>>>19)+m|0)<<18|t>>>14,l^=(t=(u^=(t=(n^=(t=(g^=(t=l+u|0)<<7|t>>>25)+l|0)<<9|t>>>23)+g|0)<<13|t>>>19)+n|0)<<18|t>>>14,b^=(t=(h^=(t=(c^=(t=(a^=(t=b+h|0)<<7|t>>>25)+b|0)<<9|t>>>23)+a|0)<<13|t>>>19)+c|0)<<18|t>>>14,r^=(t=(a^=(t=(n^=(t=(i^=(t=r+a|0)<<7|t>>>25)+r|0)<<9|t>>>23)+i|0)<<13|t>>>19)+n|0)<<18|t>>>14,s^=(t=(o^=(t=(c^=(t=(u^=(t=s+o|0)<<7|t>>>25)+s|0)<<9|t>>>23)+u|0)<<13|t>>>19)+c|0)<<18|t>>>14,l^=(t=(p^=(t=(f^=(t=(h^=(t=l+p|0)<<7|t>>>25)+l|0)<<9|t>>>23)+h|0)<<13|t>>>19)+f|0)<<18|t>>>14,b^=(t=(g^=(t=(m^=(t=(d^=(t=b+g|0)<<7|t>>>25)+b|0)<<9|t>>>23)+d|0)<<13|t>>>19)+m|0)<<18|t>>>14;e[0]=r>>>0&255,e[1]=r>>>8&255,e[2]=r>>>16&255,e[3]=r>>>24&255,e[4]=s>>>0&255,e[5]=s>>>8&255,e[6]=s>>>16&255,e[7]=s>>>24&255,e[8]=l>>>0&255,e[9]=l>>>8&255,e[10]=l>>>16&255,e[11]=l>>>24&255,e[12]=b>>>0&255,e[13]=b>>>8&255,e[14]=b>>>16&255,e[15]=b>>>24&255,e[16]=u>>>0&255,e[17]=u>>>8&255,e[18]=u>>>16&255,e[19]=u>>>24&255,e[20]=c>>>0&255,e[21]=c>>>8&255,e[22]=c>>>16&255,e[23]=c>>>24&255,e[24]=f>>>0&255,e[25]=f>>>8&255,e[26]=f>>>16&255,e[27]=f>>>24&255,e[28]=p>>>0&255,e[29]=p>>>8&255,e[30]=p>>>16&255,e[31]=p>>>24&255}(e)}var w=new Uint8Array([101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107]);function k(e,t,r,i,n,a,o){for(var s,u=new Uint8Array(16),c=new Uint8Array(64),f=0;f<16;f++)u[f]=0;for(f=0;f<8;f++)u[f]=a[f];for(;64<=n;){for(v(c,u,o,w),f=0;f<64;f++)e[t+f]=r[i+f]^c[f];for(s=1,f=8;f<16;f++)s=s+(255&u[f])|0,u[f]=255&s,s>>>=8;n-=64,t+=64,i+=64}if(0>>=8;r-=64,t+=64}if(0>>13|r<<3),t=255&e[4]|(255&e[5])<<8,this.r[2]=7939&(r>>>10|t<<6),r=255&e[6]|(255&e[7])<<8,this.r[3]=8191&(t>>>7|r<<9),t=255&e[8]|(255&e[9])<<8,this.r[4]=255&(r>>>4|t<<12),this.r[5]=t>>>1&8190,r=255&e[10]|(255&e[11])<<8,this.r[6]=8191&(t>>>14|r<<2),t=255&e[12]|(255&e[13])<<8,this.r[7]=8065&(r>>>11|t<<5),r=255&e[14]|(255&e[15])<<8,this.r[8]=8191&(t>>>8|r<<8),this.r[9]=r>>>5&127,this.pad[0]=255&e[16]|(255&e[17])<<8,this.pad[1]=255&e[18]|(255&e[19])<<8,this.pad[2]=255&e[20]|(255&e[21])<<8,this.pad[3]=255&e[22]|(255&e[23])<<8,this.pad[4]=255&e[24]|(255&e[25])<<8,this.pad[5]=255&e[26]|(255&e[27])<<8,this.pad[6]=255&e[28]|(255&e[29])<<8,this.pad[7]=255&e[30]|(255&e[31])<<8};function A(e,t,r,i,n,a){a=new E(a);return a.update(r,i,n),a.finish(e,t),0}function P(e,t,r,i,n,a){var o=new Uint8Array(16);return A(o,0,r,i,n,a),b(e,t,o,0)}function I(e,t,r,i,n){var a;if(r<32)return-1;for(j(e,0,t,0,r,i,n),A(e,16,e,32,r-32,e),a=0;a<16;a++)e[a]=0;return 0}function T(e,t,r,i,n){var a,o=new Uint8Array(32);if(r<32)return-1;if(S(o,0,32,i,n),0!==P(t,16,t,32,r-32,o))return-1;for(j(e,0,t,0,r,i,n),a=0;a<32;a++)e[a]=0;return 0}function O(e,t){for(var r=0;r<16;r++)e[r]=0|t[r]}function C(e){for(var t,r=1,i=0;i<16;i++)t=e[i]+r+65535,r=Math.floor(t/65536),e[i]=t-65536*r;e[0]+=r-1+37*(r-1)}function R(e,t,r){for(var i,n=~(r-1),a=0;a<16;a++)i=n&(e[a]^t[a]),e[a]^=i,t[a]^=i}function B(e,t){for(var r,i,n=d(),a=d(),o=0;o<16;o++)a[o]=t[o];for(C(a),C(a),C(a),r=0;r<2;r++){for(n[0]=a[0]-65517,o=1;o<15;o++)n[o]=a[o]-65535-(n[o-1]>>16&1),n[o-1]&=65535;n[15]=a[15]-32767-(n[14]>>16&1),i=n[15]>>16&1,n[14]&=65535,R(a,n,1-i)}for(o=0;o<16;o++)e[2*o]=255&a[o],e[2*o+1]=a[o]>>8}function F(e,t){var r=new Uint8Array(32),i=new Uint8Array(32);return B(r,e),B(i,t),y(r,0,i,0)}function M(e){var t=new Uint8Array(32);return B(t,e),1&t[0]}function z(e,t){for(var r=0;r<16;r++)e[r]=t[2*r]+(t[2*r+1]<<8);e[15]&=32767}function N(e,t,r){for(var i=0;i<16;i++)e[i]=t[i]+r[i]}function D(e,t,r){for(var i=0;i<16;i++)e[i]=t[i]-r[i]}function L(e,t,r){var i=0,n=0,a=0,o=0,s=0,u=0,c=0,f=0,p=0,l=0,h=0,d=0,m=0,g=0,b=0,y=0,v=0,_=0,w=0,k=0,x=0,S=0,j=0,E=0,A=0,P=0,I=0,T=0,O=0,C=0,R=0,B=r[0],F=r[1],M=r[2],z=r[3],N=r[4],D=r[5],L=r[6],q=r[7],U=r[8],H=r[9],K=r[10],V=r[11],$=r[12],G=r[13],W=r[14],Z=r[15],r=t[0];i+=r*B,n+=r*F,a+=r*M,o+=r*z,s+=r*N,u+=r*D,c+=r*L,f+=r*q,p+=r*U,l+=r*H,h+=r*K,d+=r*V,m+=r*$,g+=r*G,b+=r*W,y+=r*Z,n+=(r=t[1])*B,a+=r*F,o+=r*M,s+=r*z,u+=r*N,c+=r*D,f+=r*L,p+=r*q,l+=r*U,h+=r*H,d+=r*K,m+=r*V,g+=r*$,b+=r*G,y+=r*W,v+=r*Z,a+=(r=t[2])*B,o+=r*F,s+=r*M,u+=r*z,c+=r*N,f+=r*D,p+=r*L,l+=r*q,h+=r*U,d+=r*H,m+=r*K,g+=r*V,b+=r*$,y+=r*G,v+=r*W,_+=r*Z,o+=(r=t[3])*B,s+=r*F,u+=r*M,c+=r*z,f+=r*N,p+=r*D,l+=r*L,h+=r*q,d+=r*U,m+=r*H,g+=r*K,b+=r*V,y+=r*$,v+=r*G,_+=r*W,w+=r*Z,s+=(r=t[4])*B,u+=r*F,c+=r*M,f+=r*z,p+=r*N,l+=r*D,h+=r*L,d+=r*q,m+=r*U,g+=r*H,b+=r*K,y+=r*V,v+=r*$,_+=r*G,w+=r*W,k+=r*Z,u+=(r=t[5])*B,c+=r*F,f+=r*M,p+=r*z,l+=r*N,h+=r*D,d+=r*L,m+=r*q,g+=r*U,b+=r*H,y+=r*K,v+=r*V,_+=r*$,w+=r*G,k+=r*W,x+=r*Z,c+=(r=t[6])*B,f+=r*F,p+=r*M,l+=r*z,h+=r*N,d+=r*D,m+=r*L,g+=r*q,b+=r*U,y+=r*H,v+=r*K,_+=r*V,w+=r*$,k+=r*G,x+=r*W,S+=r*Z,f+=(r=t[7])*B,p+=r*F,l+=r*M,h+=r*z,d+=r*N,m+=r*D,g+=r*L,b+=r*q,y+=r*U,v+=r*H,_+=r*K,w+=r*V,k+=r*$,x+=r*G,S+=r*W,j+=r*Z,p+=(r=t[8])*B,l+=r*F,h+=r*M,d+=r*z,m+=r*N,g+=r*D,b+=r*L,y+=r*q,v+=r*U,_+=r*H,w+=r*K,k+=r*V,x+=r*$,S+=r*G,j+=r*W,E+=r*Z,l+=(r=t[9])*B,h+=r*F,d+=r*M,m+=r*z,g+=r*N,b+=r*D,y+=r*L,v+=r*q,_+=r*U,w+=r*H,k+=r*K,x+=r*V,S+=r*$,j+=r*G,E+=r*W,A+=r*Z,h+=(r=t[10])*B,d+=r*F,m+=r*M,g+=r*z,b+=r*N,y+=r*D,v+=r*L,_+=r*q,w+=r*U,k+=r*H,x+=r*K,S+=r*V,j+=r*$,E+=r*G,A+=r*W,P+=r*Z,d+=(r=t[11])*B,m+=r*F,g+=r*M,b+=r*z,y+=r*N,v+=r*D,_+=r*L,w+=r*q,k+=r*U,x+=r*H,S+=r*K,j+=r*V,E+=r*$,A+=r*G,P+=r*W,I+=r*Z,m+=(r=t[12])*B,g+=r*F,b+=r*M,y+=r*z,v+=r*N,_+=r*D,w+=r*L,k+=r*q,x+=r*U,S+=r*H,j+=r*K,E+=r*V,A+=r*$,P+=r*G,I+=r*W,T+=r*Z,g+=(r=t[13])*B,b+=r*F,y+=r*M,v+=r*z,_+=r*N,w+=r*D,k+=r*L,x+=r*q,S+=r*U,j+=r*H,E+=r*K,A+=r*V,P+=r*$,I+=r*G,T+=r*W,O+=r*Z,b+=(r=t[14])*B,y+=r*F,v+=r*M,_+=r*z,w+=r*N,k+=r*D,x+=r*L,S+=r*q,j+=r*U,E+=r*H,A+=r*K,P+=r*V,I+=r*$,T+=r*G,O+=r*W,C+=r*Z,y+=(r=t[15])*B,n+=38*(_+=r*M),a+=38*(w+=r*z),o+=38*(k+=r*N),s+=38*(x+=r*D),u+=38*(S+=r*L),c+=38*(j+=r*q),f+=38*(E+=r*U),p+=38*(A+=r*H),l+=38*(P+=r*K),h+=38*(I+=r*V),d+=38*(T+=r*$),m+=38*(O+=r*G),g+=38*(C+=r*W),b+=38*(R+=r*Z),i=(r=1+(i+=38*(v+=r*F))+65535)-65536*(R=Math.floor(r/65536)),n=(r=n+R+65535)-65536*(R=Math.floor(r/65536)),a=(r=a+R+65535)-65536*(R=Math.floor(r/65536)),o=(r=o+R+65535)-65536*(R=Math.floor(r/65536)),s=(r=s+R+65535)-65536*(R=Math.floor(r/65536)),u=(r=u+R+65535)-65536*(R=Math.floor(r/65536)),c=(r=c+R+65535)-65536*(R=Math.floor(r/65536)),f=(r=f+R+65535)-65536*(R=Math.floor(r/65536)),p=(r=p+R+65535)-65536*(R=Math.floor(r/65536)),l=(r=l+R+65535)-65536*(R=Math.floor(r/65536)),h=(r=h+R+65535)-65536*(R=Math.floor(r/65536)),d=(r=d+R+65535)-65536*(R=Math.floor(r/65536)),m=(r=m+R+65535)-65536*(R=Math.floor(r/65536)),g=(r=g+R+65535)-65536*(R=Math.floor(r/65536)),b=(r=b+R+65535)-65536*(R=Math.floor(r/65536)),y=(r=y+R+65535)-65536*(R=Math.floor(r/65536)),i+=R-1+37*(R-1),i=(r=1+i+65535)-65536*(R=Math.floor(r/65536)),n=(r=n+R+65535)-65536*(R=Math.floor(r/65536)),a=(r=a+R+65535)-65536*(R=Math.floor(r/65536)),o=(r=o+R+65535)-65536*(R=Math.floor(r/65536)),s=(r=s+R+65535)-65536*(R=Math.floor(r/65536)),u=(r=u+R+65535)-65536*(R=Math.floor(r/65536)),c=(r=c+R+65535)-65536*(R=Math.floor(r/65536)),f=(r=f+R+65535)-65536*(R=Math.floor(r/65536)),p=(r=p+R+65535)-65536*(R=Math.floor(r/65536)),l=(r=l+R+65535)-65536*(R=Math.floor(r/65536)),h=(r=h+R+65535)-65536*(R=Math.floor(r/65536)),d=(r=d+R+65535)-65536*(R=Math.floor(r/65536)),m=(r=m+R+65535)-65536*(R=Math.floor(r/65536)),g=(r=g+R+65535)-65536*(R=Math.floor(r/65536)),b=(r=b+R+65535)-65536*(R=Math.floor(r/65536)),y=(r=y+R+65535)-65536*(R=Math.floor(r/65536)),i+=R-1+37*(R-1),e[0]=i,e[1]=n,e[2]=a,e[3]=o,e[4]=s,e[5]=u,e[6]=c,e[7]=f,e[8]=p,e[9]=l,e[10]=h,e[11]=d,e[12]=m,e[13]=g,e[14]=b,e[15]=y}function q(e,t){L(e,t,t)}function U(e,t){for(var r=d(),i=0;i<16;i++)r[i]=t[i];for(i=253;0<=i;i--)q(r,r),2!==i&&4!==i&&L(r,r,t);for(i=0;i<16;i++)e[i]=r[i]}function H(e,t,r){for(var i,n=new Uint8Array(32),a=new Float64Array(80),o=d(),s=d(),u=d(),c=d(),f=d(),p=d(),l=0;l<31;l++)n[l]=t[l];for(n[31]=127&t[31]|64,n[0]&=248,z(a,r),l=0;l<16;l++)s[l]=a[l],c[l]=o[l]=u[l]=0;for(o[0]=c[0]=1,l=254;0<=l;--l)R(o,s,i=n[l>>>3]>>>(7&l)&1),R(u,c,i),N(f,o,u),D(o,o,u),N(u,s,c),D(s,s,c),q(c,f),q(p,o),L(o,u,o),L(u,s,f),N(f,o,u),D(o,o,u),q(s,o),D(u,c,p),L(o,u,m),N(o,o,c),L(u,u,o),L(o,c,p),L(c,s,a),q(s,f),R(o,s,i),R(u,c,i);for(l=0;l<16;l++)a[l+16]=o[l],a[l+32]=u[l],a[l+48]=s[l],a[l+64]=c[l];var h=a.subarray(32),r=a.subarray(16);return U(h,h),L(r,r,h),B(e,r),0}function K(e,t){return H(e,t,r)}function V(e,t){return o(t,32),K(e,t)}function $(e,t,r){var i=new Uint8Array(32);return H(i,r,t),_(e,n,i,w)}E.prototype.blocks=function(e,t,r){for(var i,n,a,o,s,u,c,f,p,l,h,d=this.fin?0:2048,m=this.h[0],g=this.h[1],b=this.h[2],y=this.h[3],v=this.h[4],_=this.h[5],w=this.h[6],k=this.h[7],x=this.h[8],S=this.h[9],j=this.r[0],E=this.r[1],A=this.r[2],P=this.r[3],I=this.r[4],T=this.r[5],O=this.r[6],C=this.r[7],R=this.r[8],B=this.r[9];16<=r;)n=i=0,n+=(m+=8191&(o=255&e[t+0]|(255&e[t+1])<<8))*j,n+=(g+=8191&(o>>>13|(s=255&e[t+2]|(255&e[t+3])<<8)<<3))*(5*B),n+=(b+=8191&(s>>>10|(u=255&e[t+4]|(255&e[t+5])<<8)<<6))*(5*R),n+=(y+=8191&(u>>>7|(c=255&e[t+6]|(255&e[t+7])<<8)<<9))*(5*C),i=(n+=(v+=8191&(c>>>4|(f=255&e[t+8]|(255&e[t+9])<<8)<<12))*(5*O))>>>13,n&=8191,n+=(_+=f>>>1&8191)*(5*T),n+=(w+=8191&(f>>>14|(p=255&e[t+10]|(255&e[t+11])<<8)<<2))*(5*I),n+=(k+=8191&(p>>>11|(l=255&e[t+12]|(255&e[t+13])<<8)<<5))*(5*P),n+=(x+=8191&(l>>>8|(h=255&e[t+14]|(255&e[t+15])<<8)<<8))*(5*A),a=i+=(n+=(S+=h>>>5|d)*(5*E))>>>13,a+=m*E,a+=g*j,a+=b*(5*B),a+=y*(5*R),i=(a+=v*(5*C))>>>13,a&=8191,a+=_*(5*O),a+=w*(5*T),a+=k*(5*I),a+=x*(5*P),i+=(a+=S*(5*A))>>>13,a&=8191,o=i,o+=m*A,o+=g*E,o+=b*j,o+=y*(5*B),i=(o+=v*(5*R))>>>13,o&=8191,o+=_*(5*C),o+=w*(5*O),o+=k*(5*T),o+=x*(5*I),s=i+=(o+=S*(5*P))>>>13,s+=m*P,s+=g*A,s+=b*E,s+=y*j,i=(s+=v*(5*B))>>>13,s&=8191,s+=_*(5*R),s+=w*(5*C),s+=k*(5*O),s+=x*(5*T),u=i+=(s+=S*(5*I))>>>13,u+=m*I,u+=g*P,u+=b*A,u+=y*E,i=(u+=v*j)>>>13,u&=8191,u+=_*(5*B),u+=w*(5*R),u+=k*(5*C),u+=x*(5*O),c=i+=(u+=S*(5*T))>>>13,c+=m*T,c+=g*I,c+=b*P,c+=y*A,i=(c+=v*E)>>>13,c&=8191,c+=_*j,c+=w*(5*B),c+=k*(5*R),c+=x*(5*C),f=i+=(c+=S*(5*O))>>>13,f+=m*O,f+=g*T,f+=b*I,f+=y*P,i=(f+=v*A)>>>13,f&=8191,f+=_*E,f+=w*j,f+=k*(5*B),f+=x*(5*R),p=i+=(f+=S*(5*C))>>>13,p+=m*C,p+=g*O,p+=b*T,p+=y*I,i=(p+=v*P)>>>13,p&=8191,p+=_*A,p+=w*E,p+=k*j,p+=x*(5*B),l=i+=(p+=S*(5*R))>>>13,l+=m*R,l+=g*C,l+=b*O,l+=y*T,i=(l+=v*I)>>>13,l&=8191,l+=_*P,l+=w*A,l+=k*E,l+=x*j,h=i+=(l+=S*(5*B))>>>13,h+=m*B,h+=g*R,h+=b*C,h+=y*O,i=(h+=v*T)>>>13,h&=8191,h+=_*I,h+=w*P,h+=k*A,h+=x*E,m=8191&(i=(i=((i+=(h+=S*j)>>>13)<<2)+i|0)+(n&=8191)|0),g=a+=i>>>=13,b=o&=8191,y=s&=8191,v=u&=8191,_=c&=8191,w=f&=8191,k=p&=8191,x=l&=8191,S=h&=8191,t+=16,r-=16;this.h[0]=m,this.h[1]=g,this.h[2]=b,this.h[3]=y,this.h[4]=v,this.h[5]=_,this.h[6]=w,this.h[7]=k,this.h[8]=x,this.h[9]=S},E.prototype.finish=function(e,t){var r,i,n,a,o=new Uint16Array(10);if(this.leftover){for(a=this.leftover,this.buffer[a++]=1;a<16;a++)this.buffer[a]=0;this.fin=1,this.blocks(this.buffer,0,16)}for(r=this.h[1]>>>13,this.h[1]&=8191,a=2;a<10;a++)this.h[a]+=r,r=this.h[a]>>>13,this.h[a]&=8191;for(this.h[0]+=5*r,r=this.h[0]>>>13,this.h[0]&=8191,this.h[1]+=r,r=this.h[1]>>>13,this.h[1]&=8191,this.h[2]+=r,o[0]=this.h[0]+5,r=o[0]>>>13,o[0]&=8191,a=1;a<10;a++)o[a]=this.h[a]+r,r=o[a]>>>13,o[a]&=8191;for(o[9]-=8192,i=(1^r)-1,a=0;a<10;a++)o[a]&=i;for(i=~i,a=0;a<10;a++)this.h[a]=this.h[a]&i|o[a];for(this.h[0]=65535&(this.h[0]|this.h[1]<<13),this.h[1]=65535&(this.h[1]>>>3|this.h[2]<<10),this.h[2]=65535&(this.h[2]>>>6|this.h[3]<<7),this.h[3]=65535&(this.h[3]>>>9|this.h[4]<<4),this.h[4]=65535&(this.h[4]>>>12|this.h[5]<<1|this.h[6]<<14),this.h[5]=65535&(this.h[6]>>>2|this.h[7]<<11),this.h[6]=65535&(this.h[7]>>>5|this.h[8]<<8),this.h[7]=65535&(this.h[8]>>>8|this.h[9]<<5),n=this.h[0]+this.pad[0],this.h[0]=65535&n,a=1;a<8;a++)n=(this.h[a]+this.pad[a]|0)+(n>>>16)|0,this.h[a]=65535&n;e[t+0]=this.h[0]>>>0&255,e[t+1]=this.h[0]>>>8&255,e[t+2]=this.h[1]>>>0&255,e[t+3]=this.h[1]>>>8&255,e[t+4]=this.h[2]>>>0&255,e[t+5]=this.h[2]>>>8&255,e[t+6]=this.h[3]>>>0&255,e[t+7]=this.h[3]>>>8&255,e[t+8]=this.h[4]>>>0&255,e[t+9]=this.h[4]>>>8&255,e[t+10]=this.h[5]>>>0&255,e[t+11]=this.h[5]>>>8&255,e[t+12]=this.h[6]>>>0&255,e[t+13]=this.h[6]>>>8&255,e[t+14]=this.h[7]>>>0&255,e[t+15]=this.h[7]>>>8&255},E.prototype.update=function(e,t,r){var i,n;if(this.leftover){for(r<(n=16-this.leftover)&&(n=r),i=0;i>>16,E=65535&(k=z),A=k>>>16,S+=65535&(x=((d=U)>>>14|(s=B)<<18)^(U>>>18|B<<14)^(B>>>9|U<<23)),j+=x>>>16,E+=65535&(k=(B>>>14|U<<18)^(B>>>18|U<<14)^(U>>>9|B<<23)),A+=k>>>16,S+=65535&(x=U&(m=H)^~U&(g=K)),j+=x>>>16,E+=65535&(k=B&(u=F)^~B&(c=M)),A+=k>>>16,k=Z[2*_],S+=65535&(x=Z[2*_+1]),j+=x>>>16,E+=65535&k,A+=k>>>16,k=P[_%16],j+=(x=I[_%16])>>>16,E+=65535&k,A+=k>>>16,E+=(j+=(S+=65535&x)>>>16)>>>16,S=65535&(x=v=65535&S|j<<16),j=x>>>16,E=65535&(k=y=65535&E|(A+=E>>>16)<<16),A=k>>>16,S+=65535&(x=(N>>>28|T<<4)^(T>>>2|N<<30)^(T>>>7|N<<25)),j+=x>>>16,E+=65535&(k=(T>>>28|N<<4)^(N>>>2|T<<30)^(N>>>7|T<<25)),A+=k>>>16,j+=(x=N&D^N&L^D&L)>>>16,E+=65535&(k=T&O^T&C^O&C),A+=k>>>16,f=65535&(E+=(j+=(S+=65535&x)>>>16)>>>16)|(A+=E>>>16)<<16,b=65535&S|j<<16,S=65535&(x=h),j=x>>>16,E=65535&(k=o),A=k>>>16,j+=(x=v)>>>16,E+=65535&(k=y),A+=k>>>16,O=T,C=n,R=a,B=65535&(E+=(j+=(S+=65535&x)>>>16)>>>16)|(A+=E>>>16)<<16,F=s,M=u,z=c,T=f,D=N,L=p,q=l,U=65535&S|j<<16,H=d,K=m,V=g,N=b,_%16==15)for(w=0;w<16;w++)k=P[w],S=65535&(x=I[w]),j=x>>>16,E=65535&k,A=k>>>16,k=P[(w+9)%16],S+=65535&(x=I[(w+9)%16]),j+=x>>>16,E+=65535&k,A+=k>>>16,y=P[(w+1)%16],S+=65535&(x=((v=I[(w+1)%16])>>>1|y<<31)^(v>>>8|y<<24)^(v>>>7|y<<25)),j+=x>>>16,E+=65535&(k=(y>>>1|v<<31)^(y>>>8|v<<24)^y>>>7),A+=k>>>16,y=P[(w+14)%16],j+=(x=((v=I[(w+14)%16])>>>19|y<<13)^(y>>>29|v<<3)^(v>>>6|y<<26))>>>16,E+=65535&(k=(y>>>19|v<<13)^(v>>>29|y<<3)^y>>>6),A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,P[w]=65535&E|A<<16,I[w]=65535&S|j<<16;S=65535&(x=N),j=x>>>16,E=65535&(k=T),A=k>>>16,k=e[0],j+=(x=t[0])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[0]=T=65535&E|A<<16,t[0]=N=65535&S|j<<16,S=65535&(x=D),j=x>>>16,E=65535&(k=O),A=k>>>16,k=e[1],j+=(x=t[1])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[1]=O=65535&E|A<<16,t[1]=D=65535&S|j<<16,S=65535&(x=L),j=x>>>16,E=65535&(k=C),A=k>>>16,k=e[2],j+=(x=t[2])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[2]=C=65535&E|A<<16,t[2]=L=65535&S|j<<16,S=65535&(x=q),j=x>>>16,E=65535&(k=R),A=k>>>16,k=e[3],j+=(x=t[3])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[3]=R=65535&E|A<<16,t[3]=q=65535&S|j<<16,S=65535&(x=U),j=x>>>16,E=65535&(k=B),A=k>>>16,k=e[4],j+=(x=t[4])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[4]=B=65535&E|A<<16,t[4]=U=65535&S|j<<16,S=65535&(x=H),j=x>>>16,E=65535&(k=F),A=k>>>16,k=e[5],j+=(x=t[5])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[5]=F=65535&E|A<<16,t[5]=H=65535&S|j<<16,S=65535&(x=K),j=x>>>16,E=65535&(k=M),A=k>>>16,k=e[6],j+=(x=t[6])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[6]=M=65535&E|A<<16,t[6]=K=65535&S|j<<16,S=65535&(x=V),j=x>>>16,E=65535&(k=z),A=k>>>16,k=e[7],j+=(x=t[7])>>>16,E+=65535&k,A+=k>>>16,A+=(E+=(j+=(S+=65535&x)>>>16)>>>16)>>>16,e[7]=z=65535&E|A<<16,t[7]=V=65535&S|j<<16,$+=128,i-=128}return i}function Q(e,t,r){var i,n=new Int32Array(8),a=new Int32Array(8),o=new Uint8Array(256),s=r;for(n[0]=1779033703,n[1]=3144134277,n[2]=1013904242,n[3]=2773480762,n[4]=1359893119,n[5]=2600822924,n[6]=528734635,n[7]=1541459225,a[0]=4089235720,a[1]=2227873595,a[2]=4271175723,a[3]=1595750129,a[4]=2917565137,a[5]=725511199,a[6]=4215389547,a[7]=327033209,Y(n,a,t,r),r%=128,i=0;i>(7&n)&1),X(t,e),X(e,e),J(e,t,i)}function re(e,t){var r=[d(),d(),d(),d()];O(r[0],i),O(r[1],s),O(r[2],f),L(r[3],i,s),te(e,r,t)}function ie(e,t,r){var i,n=new Uint8Array(64),a=[d(),d(),d(),d()];for(r||o(t,32),Q(n,t,32),n[0]&=248,n[31]&=127,n[31]|=64,re(a,n),ee(e,a),i=0;i<32;i++)t[i+32]=e[i];return 0}var ne,ae=new Float64Array([237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16]);function oe(e,t){for(var r,i,n,a=63;32<=a;--a){for(r=0,i=a-32,n=a-12;i>8,t[i]-=256*r;t[i]+=r,t[a]=0}for(i=r=0;i<32;i++)t[i]+=r-(t[31]>>4)*ae[i],r=t[i]>>8,t[i]&=255;for(i=0;i<32;i++)t[i]-=r*ae[i];for(a=0;a<32;a++)t[a+1]+=t[a]>>8,e[a]=255&t[a]}function se(e){for(var t=new Float64Array(64),r=0;r<64;r++)t[r]=e[r];for(r=0;r<64;r++)e[r]=0;oe(e,t)}function ue(e,t,r,i){var n,a=new Uint8Array(64),o=new Uint8Array(64),s=new Uint8Array(64),u=new Float64Array(64),c=[d(),d(),d(),d()];Q(a,i,32),a[0]&=248,a[31]&=127,a[31]|=64;for(var f=r+64,p=0;p>7&&D(e[0],c,e[0]),L(e[3],e[0],e[1])}function fe(e,t,r,i){var n,a=new Uint8Array(32),o=new Uint8Array(64),s=[d(),d(),d(),d()],u=[d(),d(),d(),d()];if(r<64)return-1;if(ce(u,i))return-1;for(n=0;n= 0x80 (not a basic code point)","invalid-input":"Invalid input"},O=Math.floor,C=String.fromCharCode;function R(e){throw new RangeError(o[e])}function s(e,t){var r=e.split("@"),i="";return 1>1,e+=O(e/t);455O((T-i)/f))&&R("overflow"),i+=l*f;var h=p<=a?1:a+26<=p?26:p-a;if(lO(T/h)&&R("overflow"),f*=h}var d=t.length+1,a=M(i-c,d,0==c);O(i/d)>T-n&&R("overflow"),n+=O(i/d),i%=d,t.splice(i++,0,n)}return String.fromCodePoint.apply(String,t)}function l(e){var t=[],r=(e=B(e)).length,i=128,n=0,a=72,o=!0,s=!1,u=void 0;try{for(var c=e[Symbol.iterator]();!(o=(f=c.next()).done);o=!0){var f=f.value;f<128&&t.push(C(f))}}catch(e){s=!0,u=e}finally{try{!o&&c.return&&c.return()}finally{if(s)throw u}}var p=t.length,l=p;for(p&&t.push("-");lO((T-n)/v)&&R("overflow"),n+=(h-i)*v,i=h;var _=!0,w=!1,k=void 0;try{for(var x=e[Symbol.iterator]();!(_=(S=x.next()).done);_=!0){var S=S.value;if(ST&&R("overflow"),S==i){for(var j=n,E=36;;E+=36){var A=E<=a?1:a+26<=E?26:E-a;if(j>6|192).toString(16).toUpperCase()+"%"+(63&e|128).toString(16).toUpperCase():"%"+(e>>12|224).toString(16).toUpperCase()+"%"+(e>>6&63|128).toString(16).toUpperCase()+"%"+(63&e|128).toString(16).toUpperCase()}function b(e){for(var t="",r=0,i=e.length;rA-Z\\x5E-\\x7E]",'[\\"\\\\]')),Q=new RegExp(W,"g"),X=new RegExp("(?:(?:%[EFef][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f])|(?:%[89A-Fa-f][0-9A-Fa-f]%[0-9A-Fa-f][0-9A-Fa-f])|(?:%[0-9A-Fa-f][0-9A-Fa-f]))","g"),J=new RegExp(j("[^]","[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]","[\\.]",'[\\"]',Y),"g"),ee=new RegExp(j("[^]",W,"[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]"),"g"),te=ee;function re(e){var t=b(e);return t.match(Q)?t:e}var Z={scheme:"mailto",parse:function(e,t){var r=e,i=r.to=r.path?r.path.split(","):[];if(r.path=void 0,r.query){for(var n=!1,a={},o=r.query.split("&"),s=0,u=o.length;s",'"',"`"," ","\r","\n","\t"]),T=["'"].concat(r),O=["%","/","?",";","#"].concat(T),C=["/","?","#"],R=/^[+a-z0-9A-Z_-]{0,63}$/,B=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,F={javascript:!0,"javascript:":!0},M={javascript:!0,"javascript:":!0},z={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},N=e("querystring");function n(e,t,r){if(e&&A.isObject(e)&&e instanceof w)return e;var i=new w;return i.parse(e,t,r),i}w.prototype.parse=function(e,t,r){if(!A.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+_typeof(e));var i=e.indexOf("?"),n=-1!==i&&i>>((3&t)<<3)&255;return n})},{}],484:[function(e,t,r){var o=e("./lib/rng"),s=e("./lib/bytesToUuid");t.exports=function(e,t,r){var i=t&&r||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var n=(e=e||{}).random||(e.rng||o)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,t)for(var a=0;a<16;++a)t[i+a]=n[a];return t||s(n)}},{"./lib/bytesToUuid":482,"./lib/rng":483}],485:[function(e,t,r){var a=e("assert-plus"),i=e("util"),n=e("extsprintf"),o=e("core-util-is").isError,s=n.sprintf;function u(e){var t,r,i,n;if(a.object(e,"args"),a.bool(e.strict,"args.strict"),a.array(e.argv,"args.argv"),0===(t=e.argv).length)r={},i=[];else if(o(t[0]))r={cause:t[0]},i=t.slice(1);else if("object"===_typeof(t[0])){for(n in r={},t[0])r[n]=t[0][n];i=t.slice(1)}else a.string(t[0],"first argument to VError, SError, or WError constructor must be a string, object, or Error"),r={},i=t;return a.object(r),{options:r,shortmessage:0===(i=!r.strict&&!e.strict?i.map(function(e){return null===e?"null":void 0===e?"undefined":e}):i).length?"":s.apply(null,i)}}function c(){var e,t,r,i=Array.prototype.slice.call(arguments,0);if(!(this instanceof c))return t=Object.create(c.prototype),c.apply(t,arguments),t;if((e=u({argv:i,strict:!1})).options.name&&(a.string(e.options.name,'error\'s "name" must be a string'),this.name=e.options.name),this.jse_shortmsg=e.shortmessage,t=e.shortmessage,(i=e.options.cause)&&(a.ok(o(i),"cause is not an Error"),this.jse_cause=i,e.options.skipCauseMessage||(t+=": "+i.message)),this.jse_info={},e.options.info)for(r in e.options.info)this.jse_info[r]=e.options.info[r];return this.message=t,Error.call(this,t),Error.captureStackTrace&&(t=e.options.constructorOpt||this.constructor,Error.captureStackTrace(this,t)),this}function f(){var e,t=Array.prototype.slice.call(arguments,0);return this instanceof f?(t=(e=u({argv:t,strict:!0})).options,c.call(this,t,"%s",e.shortmessage),this):(e=Object.create(f.prototype),f.apply(e,arguments),e)}function p(e){a.array(e,"list of errors"),a.ok(0=this.buffer.length)){e>this.buffer.length&&(e=this.buffer.length);var t=this.buffer.slice(this.counter,this.counter+e);return this.counter+=e,t}}},{key:"read",value:function(e){e>this.buffer.length&&(e=this.buffer.length);var t=this.buffer.slice(this.counter,this.counter+e);return this.counter+=e,Array.from(t)}},{key:"readBool",value:function(){var e=this.read(1)[0];if(255===e)return!0;if(0===e)return!1;throw new i("read_bool() expected 0xff or 0x00; got +"+e)}},{key:"readVaruint",value:function(){for(var e,t=0,r=0;t|=(127&(e=this.read(1)[0]))< "+e);if(r>=7}}},{key:"writeByte",value:function(e){var t;this.length>=this.buffer.length&&(t=2*this.length,(t=new Uint8Array(t)).set(this.buffer,0),this.buffer=t),isNaN(e)?this.buffer[this.length]=e.codePointAt():this.buffer[this.length]=e,this.length++}},{key:"writeBytes",value:function(e){var t=this;e.forEach(function(e){t.writeByte(e)})}},{key:"writeVarbytes",value:function(e){this.writeVaruint(e.length),this.writeBytes(e)}},{key:"toString",value:function(){return this.buffer.toHex(0)}}]),e}();m.exports={StreamDeserialization:p,StreamSerialization:l,DeserializationError:i,BadMagicError:n,UnsupportedMajorVersion:a,TruncationError:o,TrailingGarbageError:s,RecursionLimitError:u,SerializerTypeError:c,SerializerValueError:f,ValueError:e,TypeError:t}}).call(this)}).call(this,d("buffer").Buffer)},{"./extend-error.js":492,"./utils.js":498,buffer:186}],490:[function(e,t,r){"use strict";var a=e("./ops.js"),o=e("./timestamp.js"),i=e("./utils.js"),s=e("./context.js"),u=[0,79,112,101,110,84,105,109,101,115,116,97,109,112,115,0,0,80,114,111,111,102,0,191,137,226,232,132,232,146,148],e=function(){function n(e,t){if(_classCallCheck2(this,n),!(e instanceof a.Op&&t instanceof o))throw new s.ValueError("Invalid Timestamp or fileHashOp");if(t.msg.length!==e._DIGEST_LENGTH())throw new s.ValueError("Timestamp message length and fileHashOp digest length differ");this.fileHashOp=e,this.timestamp=t}return _createClass2(n,[{key:"fileDigest",value:function(){return this.timestamp.msg}},{key:"serialize",value:function(e){e.writeBytes(u),e.writeVaruint(1),this.fileHashOp.serialize(e),e.writeBytes(this.timestamp.msg),this.timestamp.serialize(e)}},{key:"serializeToBytes",value:function(){var e=new s.StreamSerialization;return this.serialize(e),e.getOutput()}},{key:"toString",value:function(){var e="DetachedTimestampFile\n";return e+="fileHashOp: "+this.fileHashOp.toString()+"\n",e+="timestamp: "+this.timestamp.toString()+"\n"}},{key:"toJson",value:function(){var e={};e.hash=i.bytesToHex(this.fileDigest()),e.op=this.fileHashOp._HASHLIB_NAME(),e.timestamp=this.timestamp.toJson()}},{key:"equals",value:function(e){return e instanceof n&&(!!e.fileHashOp.equals(this.fileHashOp)&&!!e.timestamp.equals(this.timestamp))}}],[{key:"deserialize",value:function(e){var t;if(e instanceof s.StreamDeserialization)t=e;else if(e instanceof Array)t=new s.StreamDeserialization(e);else if(e instanceof Uint8Array)t=new s.StreamDeserialization(Array.from(e));else{if(!(e instanceof ArrayBuffer))throw new Error("StreamDeserialization deserialize: Invalid param");t=new s.StreamDeserialization(Array.from(e))}t.assertMagic(u);var r=t.readVaruint();if(1!==r)throw new s.UnsupportedMajorVersion("Version "+r+" detached timestamp files are not supported");e=a.CryptOp.deserialize(t),r=t.readBytes(e._DIGEST_LENGTH()),r=o.deserialize(t,r);return t.assertEof(),new n(e,r)}},{key:"fromBytes",value:function(e,t){if(!(e instanceof a.Op))throw new Error("DetachedTimestampFile: Invalid fileHashOp param");if(t instanceof s.StreamDeserialization)i=e.hashFd(t);else if(t instanceof Array)var r=new s.StreamDeserialization(t),i=e.hashFd(r);else if(t instanceof Uint8Array){r=new s.StreamDeserialization(Array.from(t));i=e.hashFd(r)}else{if(!(t instanceof ArrayBuffer))throw new Error("DetachedTimestampFile: Invalid buffer param");t=new s.StreamDeserialization(Array.from(t));i=e.hashFd(t)}return new n(e,new o(i))}},{key:"fromHash",value:function(e,t){if(!(e instanceof a.Op))throw new Error("DetachedTimestampFile: Invalid fileHashOpss param");if(t instanceof Array)return new n(e,new o(t));if(t instanceof ArrayBuffer||t instanceof Uint8Array)return new n(e,new o(Array.from(t)));throw new Error("DetachedTimestampFile: Invalid fdHash param")}}]),n}();t.exports=e},{"./context.js":489,"./ops.js":496,"./timestamp.js":497,"./utils.js":498}],491:[function(e,t,r){"use strict";var i=e("request-promise");e("./extend-error.js");var n=Error.extend("URLError"),a="https://blockstream.info/api";t.exports=function(){function t(){var e=0(new i)._MAX_URI_LENGTH())return console.error("URI exceeds maximum length"),!1;for(var t=0;tt.calendars.length)return console.log("m cannot be greater than available calendar neither less or equal 0"),new u(function(e,t){t(new Error("m cannot be greater than available calendar neither less or equal 0"))})}else t.m=1,2<=t.calendars.length&&(t.m=2);return this.createTimestamp(r,t.calendars,t.m).then(function(e){if(void 0===e)throw new Error("Error on timestamp creation")})},createTimestamp:function(r,e,t){var i=[];return e&&e.forEach(function(e){var t=new f.RemoteCalendar(e);i.push(t.submit(r.msg)),console.log("Submitting to remote calendar "+e)}),u.all(i.map(c.softFail)).then(function(e){return e.filter(function(e){return!(e instanceof Error)&&void 0!==e}).forEach(function(e){r.merge(e)}),r})},makeMerkleTree:function(e){var r=[];return e.forEach(function(e){if(e instanceof a)try{var t=c.randBytes(16),t=e.timestamp.add(new i.OpAppend(c.arrayToBytes(t))).add(new i.OpSHA256);r.push(t)}catch(e){return}else console.error("Invalid input")}),l.makeMerkleTree(r)},verify:function(e,t,r){var i=this;return c.arrEq(e.fileDigest(),t.fileDigest())?this.upgradeTimestamp(e.timestamp,r).then(function(){return i.verifyTimestamp(e.timestamp,r)}):(console.error("Expected digest "+c.bytesToHex(e.fileDigest())),console.error("File does not match original!"),new u(function(e,t){t(new Error("File does not match original!"))}))},verifyTimestamp:function(e,r){var i=[],n=this;function a(e,t){return e.attestedTimet.attestedTime?1:0}return e.allAttestations().forEach(function(e,t){i.push(n.verifyAttestation(e,t,r))}),u.all(i.map(c.softFail)).then(function(e){var t=e.filter(function(e){return e.constructor===p.VerificationError?e:void 0});if(0this._MAX_MSG_LENGTH())){e=this.call(e);return e.length>this._MAX_RESULT_LENGTH()&&console.error("Error : Result too long;"),e}console.error("Error : Message too long;")}}],[{key:"deserialize",value:function(e){return this.tag=e.readBytes(1)[0],t.deserializeFromTag(e,this.tag)}},{key:"deserializeFromTag",value:function(e,t){if(void 0!==a.get(t))return a.get(t).deserializeFromTag(e,t);console.error("Unknown operation tag: ",n.bytesToHex([t]))}}]),t}(),e=function(){_inherits(i,s);var r=_createSuper(i);function i(e){var t;return _classCallCheck2(this,i),(t=r.call(this)).arg=void 0===e?[]:e,t}return _createClass2(i,[{key:"serialize",value:function(e){_get(_getPrototypeOf(i.prototype),"serialize",this).call(this,e),e.writeVarbytes(this.arg)}},{key:"toString",value:function(){return this._TAG_NAME()+" "+n.bytesToHex(this.arg)}}],[{key:"deserializeFromTag",value:function(e,t){if(void 0!==a.get(t)){e=e.readVarbytes((new s)._MAX_RESULT_LENGTH(),1);return new(a.get(t))(e)}}}]),i}(),t=function(){_inherits(i,e);var r=_createSuper(i);function i(e){var t;return _classCallCheck2(this,i),(t=r.call(this,e)).arg=void 0===e?[]:e,t}return _createClass2(i,[{key:"_TAG",value:function(){return 240}},{key:"_TAG_NAME",value:function(){return"append"}},{key:"call",value:function(e){return e.concat(this.arg)}},{key:"equals",value:function(e){return e instanceof i&&n.arrEq(this.arg,e.arg)}}],[{key:"deserializeFromTag",value:function(e,t){return _get(_getPrototypeOf(i),"deserializeFromTag",this).call(this,e,t)}}]),i}(),r=function(){_inherits(i,e);var r=_createSuper(i);function i(e){var t;return _classCallCheck2(this,i),(t=r.call(this,e)).arg=void 0===e?[]:e,t}return _createClass2(i,[{key:"_TAG",value:function(){return 241}},{key:"_TAG_NAME",value:function(){return"prepend"}},{key:"call",value:function(e){return this.arg.concat(e)}},{key:"equals",value:function(e){return e instanceof i&&n.arrEq(this.arg,e.arg)}}],[{key:"deserializeFromTag",value:function(e,t){return _get(_getPrototypeOf(i),"deserializeFromTag",this).call(this,e,t)}}]),i}(),i=function(){_inherits(t,s);var e=_createSuper(t);function t(){return _classCallCheck2(this,t),e.apply(this,arguments)}return _createClass2(t,[{key:"toString",value:function(){return this._TAG_NAME()}}],[{key:"deserializeFromTag",value:function(e,t){if(void 0!==a.get(t))return new(a.get(t));console.error("Unknown operation tag: ",n.bytesToHex([t]))}}]),t}(),u=function(){_inherits(r,i);var e=_createSuper(r);function r(){return _classCallCheck2(this,r),e.apply(this,arguments)}return _createClass2(r,[{key:"_TAG",value:function(){return 242}},{key:"_TAG_NAME",value:function(){return"reverse"}},{key:"call",value:function(e){return 0===e.length&&console.error("Can't reverse an empty message"),e.slice().reverse()}},{key:"equals",value:function(e){return e instanceof r&&n.arrEq(this.arg,e.arg)}}],[{key:"deserializeFromTag",value:function(e,t){return _get(_getPrototypeOf(r),"deserializeFromTag",this).call(this,e,t)}}]),r}(),c=function(){_inherits(r,i);var e=_createSuper(r);function r(){return _classCallCheck2(this,r),e.apply(this,arguments)}return _createClass2(r,[{key:"_TAG",value:function(){return 243}},{key:"_TAG_NAME",value:function(){return"hexlify"}},{key:"_MAX_MSG_LENGTH",value:function(){return i._MAX_RESULT_LENGTH()}},{key:"call",value:function(e){0===e.length&&console.error("Can't hexlify an empty message")}},{key:"equals",value:function(e){return e instanceof r&&n.arrEq(this.arg,e.arg)}}],[{key:"deserializeFromTag",value:function(e,t){return _get(_getPrototypeOf(r),"deserializeFromTag",this).call(this,e,t)}}]),r}(),f=function(){_inherits(r,i);var e=_createSuper(r);function r(){return _classCallCheck2(this,r),e.apply(this,arguments)}return _createClass2(r,[{key:"_HASHLIB_NAME",value:function(){return 0}},{key:"call",value:function(e,t){for(var r=o.createHash(e._HASHLIB_NAME()).update(d.from(t)).digest(),i=[r.length],n=0;n(new m.Op)._MAX_MSG_LENGTH())throw new TypeError("Message exceeds Op length limit; "+e.length+" > "+(new m.Op)._MAX_MSG_LENGTH());this.msg=e,this.attestations=[],this.ops=new Map}return _createClass2(l,[{key:"getDigest",value:function(){return this.msg}},{key:"serialize",value:function(r){var i=this;if(!this.attestations&&!this.ops)throw new a.ValueError("An empty timestamp can't be serialized");var n,e=this.attestations;if(e.sort(function(e,t){return e.compareTo(t)}),1 "+t.toString()+c(o,n,i)+"\n",f+=e.strTree(a+1,o)});else if(0>>4).toString(16)),t.push((15&e[r]).toString(16));return t.join("")},r.charsToHex=function(e){for(var t=[],r=0;r>>4).toString(16)),t.push((15&i).toString(16))}return t.join("")},r.charToByte=function(e){return e.charCodeAt(0)},r.charsToBytes=function(e){for(var t=[],r=0;r { + const { checkSession } = useAuth() const authState = useAppSelector((state) => state.auth) useEffect(() => { @@ -23,16 +26,17 @@ const App = () => { window.location.hostname = 'localhost' } - const authController = new AuthController() - authController.checkSession() - }, []) + checkSession() + }, [checkSession]) const handleRootRedirect = () => { if (authState.loggedIn) return appPrivateRoutes.homePage + const callbackPathEncoded = btoa( window.location.href.split(`${window.location.origin}/#`)[1] ) - return `${appPublicRoutes.login}?callbackPath=${callbackPathEncoded}` + + return `${appPublicRoutes.landingPage}?callbackPath=${callbackPathEncoded}` } // Hide route only if loggedIn and r.hiddenWhenLoggedIn are both true diff --git a/src/assets/images/nostr-logo.png b/src/assets/images/nostr-logo.png new file mode 100644 index 0000000..ea73239 Binary files /dev/null and b/src/assets/images/nostr-logo.png differ diff --git a/src/components/AppBar/AppBar.tsx b/src/components/AppBar/AppBar.tsx index 6a5862d..68b04dd 100644 --- a/src/components/AppBar/AppBar.tsx +++ b/src/components/AppBar/AppBar.tsx @@ -37,30 +37,19 @@ export const AppBar = () => { const [anchorElUser, setAnchorElUser] = useState(null) const authState = useAppSelector((state) => state.auth) - const metadataState = useAppSelector((state) => state.metadata) - const userRobotImage = useAppSelector((state) => state.userRobotImage) + const userProfile = useAppSelector((state) => state.user.profile) + const userRobotImage = useAppSelector((state) => state.user.robotImage) useEffect(() => { - if (metadataState) { - if (metadataState.content) { - const profileMetadata = JSON.parse(metadataState.content) - const { picture } = profileMetadata - - if (picture || userRobotImage) { - setUserAvatar(picture || userRobotImage) - } - - const npub = authState.usersPubkey - ? hexToNpub(authState.usersPubkey) - : '' - - setUsername(getProfileUsername(npub, profileMetadata)) - } else { - setUserAvatar(userRobotImage || '') - setUsername('') - } + const npub = authState.usersPubkey ? hexToNpub(authState.usersPubkey) : '' + if (userProfile) { + setUserAvatar(userProfile.image || userRobotImage || '') + setUsername(getProfileUsername(npub, userProfile)) + } else { + setUserAvatar('') + setUsername(getProfileUsername(npub)) } - }, [metadataState, userRobotImage, authState.usersPubkey]) + }, [userRobotImage, authState.usersPubkey, userProfile]) const handleOpenUserMenu = (event: React.MouseEvent) => { setAnchorElUser(event.currentTarget) @@ -121,7 +110,17 @@ export const AppBar = () => { - Logo navigate('/')} /> + Logo { + if (['', '#/'].includes(window.location.hash)) { + location.reload() + } else { + navigate('/') + } + }} + /> diff --git a/src/components/ButtonUnderline/index.tsx b/src/components/ButtonUnderline/index.tsx new file mode 100644 index 0000000..8301d90 --- /dev/null +++ b/src/components/ButtonUnderline/index.tsx @@ -0,0 +1,24 @@ +import { PropsWithChildren } from 'react' +import styles from './style.module.scss' + +interface ButtonUnderlineProps { + onClick: (event: React.MouseEvent) => void + disabled?: boolean | undefined +} + +export const ButtonUnderline = ({ + onClick, + disabled = false, + children +}: PropsWithChildren) => { + return ( + + ) +} diff --git a/src/components/ButtonUnderline/style.module.scss b/src/components/ButtonUnderline/style.module.scss new file mode 100644 index 0000000..a357362 --- /dev/null +++ b/src/components/ButtonUnderline/style.module.scss @@ -0,0 +1,25 @@ +@import '../../styles/colors.scss'; + +.button { + color: $primary-main !important; + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + + width: max-content; + margin: 0 auto; + + // Override default styling + border: none !important; + outline: none !important; + + // Override leaky css in sign page + background: transparent !important; + + &:focus, + &:hover { + text-decoration: underline; + text-decoration-color: inherit; + } +} diff --git a/src/components/DisplaySigit/index.tsx b/src/components/DisplaySigit/index.tsx index ab36851..5147b45 100644 --- a/src/components/DisplaySigit/index.tsx +++ b/src/components/DisplaySigit/index.tsx @@ -1,5 +1,10 @@ import { Meta } from '../../types' -import { SigitCardDisplayInfo, SigitStatus, SignStatus } from '../../utils' +import { + hexToNpub, + SigitCardDisplayInfo, + SigitStatus, + SignStatus +} from '../../utils' import { Link } from 'react-router-dom' import { formatTimestamp, npubToHex } from '../../utils' import { appPublicRoutes, appPrivateRoutes } from '../../routes' @@ -20,6 +25,7 @@ import styles from './style.module.scss' import { getExtensionIconLabel } from '../getExtensionIconLabel' import { useSigitMeta } from '../../hooks/useSigitMeta' import { extractFileExtensions } from '../../utils/file' +import { useAppSelector } from '../../hooks' type SigitProps = { sigitCreateId: string @@ -32,27 +38,32 @@ export const DisplaySigit = ({ parsedMeta, sigitCreateId: sigitCreateId }: SigitProps) => { + const { usersPubkey } = useAppSelector((state) => state.auth) + const { title, createdAt, submittedBy, signers, signedStatus, isValid } = parsedMeta const { signersStatus, fileHashes } = useSigitMeta(meta) const { extensions, isSame } = extractFileExtensions(Object.keys(fileHashes)) + const currentUserNpub: string = usersPubkey ? hexToNpub(usersPubkey) : '' + const currentUserNextSigner = + signersStatus[currentUserNpub as `npub1${string}`] === SignStatus.Awaiting + return (
- {signedStatus === SigitStatus.Complete && ( + {signedStatus === SigitStatus.Complete || !currentUserNextSigner ? ( - )} - {signedStatus !== SigitStatus.Complete && ( + ) : ( )} +

{title}

{submittedBy && ( diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index 076c6fb..71fef1c 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -8,335 +8,95 @@ import { Select } from '@mui/material' import styles from './style.module.scss' -import React, { useEffect, useState } from 'react' -import { ProfileMetadata, User, UserRole } from '../../types' -import { MouseState, PdfPage, DrawnField, DrawTool } from '../../types/drawing' +import React, { useCallback, useEffect, useState } from 'react' +import { User, UserRole, KeyboardCode } from '../../types' +import { MouseState, DrawnField, DrawTool } from '../../types/drawing' import { hexToNpub, npubToHex, getProfileUsername } from '../../utils' import { SigitFile } from '../../utils/file' import { getToolboxLabelByMarkType } from '../../utils/mark' -import { FileDivider } from '../FileDivider' -import { ExtensionFileBox } from '../ExtensionFileBox' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf' import { useScale } from '../../hooks/useScale' import { AvatarIconButton } from '../UserAvatarIconButton' import { UserAvatar } from '../UserAvatar' -import _ from 'lodash' +import { Updater } from 'use-immer' +import { FileItem } from './internal/FileItem' +import { FileDivider } from '../FileDivider' +import { Counterpart } from './internal/Counterpart' + +const MINIMUM_RECT_SIZE = { + width: 10, + height: 10 +} as const +import { NDKUserProfile } from '@nostr-dev-kit/ndk' const DEFAULT_START_SIZE = { width: 140, height: 40 } as const -interface Props { +interface HideSignersForDrawnField { + [key: number]: boolean +} + +type PageIndexer = [file: number, page: number] +type FieldIndexer = [...PageIndexer, field: number] + +interface DrawPdfFieldsProps { users: User[] - metadata: { [key: string]: ProfileMetadata } + userProfiles: { [key: string]: NDKUserProfile } sigitFiles: SigitFile[] - setSigitFiles: React.Dispatch> + updateSigitFiles: Updater selectedTool?: DrawTool } -export const DrawPDFFields = (props: Props) => { - const { selectedTool, sigitFiles, setSigitFiles, users } = props +export const DrawPDFFields = ({ + selectedTool, + userProfiles, + sigitFiles, + updateSigitFiles, + users +}: DrawPdfFieldsProps) => { + const { to, from } = useScale() const signers = users.filter((u) => u.role === UserRole.signer) const defaultSignerNpub = signers.length ? hexToNpub(signers[0].pubkey) : '' const [lastSigner, setLastSigner] = useState(defaultSignerNpub) + const [hideSignersForDrawnField, setHideSignersForDrawnField] = + useState({}) + /** * Return first pubkey that is present in the signers list * @param pubkeys * @returns available pubkey or empty string */ - const getAvailableSigner = (...pubkeys: string[]) => { - const availableSigner: string | undefined = pubkeys.find((pubkey) => - signers.some((s) => s.pubkey === npubToHex(pubkey)) - ) - return availableSigner || '' - } + const getAvailableSigner = useCallback( + (...pubkeys: string[]) => { + const availableSigner: string | undefined = pubkeys.find((pubkey) => + signers.some((s) => s.pubkey === npubToHex(pubkey)) + ) + return availableSigner || '' + }, + [signers] + ) - const { to, from } = useScale() - - const [mouseState, setMouseState] = useState({ - clicked: false - }) - - const [activeDrawnField, setActiveDrawnField] = useState<{ - fileIndex: number - pageIndex: number - drawnFieldIndex: number - }>() + const [mouseState, setMouseState] = useState({}) + const [indexer, setIndexer] = useState() + const [field, setField] = useState< + DrawnField & { + x: number + y: number + } + >() + const [lastIndexer, setLastIndexer] = useState() const isActiveDrawnField = ( fileIndex: number, pageIndex: number, drawnFieldIndex: number ) => - activeDrawnField?.fileIndex === fileIndex && - activeDrawnField?.pageIndex === pageIndex && - activeDrawnField?.drawnFieldIndex === drawnFieldIndex - - /** - * Drawing events - */ - useEffect(() => { - window.addEventListener('pointerup', handlePointerUp) - window.addEventListener('pointercancel', handlePointerUp) - - return () => { - window.removeEventListener('pointerup', handlePointerUp) - window.removeEventListener('pointercancel', handlePointerUp) - } - }, []) - - const refreshPdfFiles = () => { - setSigitFiles([...sigitFiles]) - } - - /** - * Fired only on when left (primary pointer interaction) clicking page image - * Creates new drawnElement and pushes in the array - * It is re rendered and visible right away - * - * @param event Pointer event - * @param page PdfPage where press happened - */ - const handlePointerDown = ( - event: React.PointerEvent, - page: PdfPage, - fileIndex: number, - pageIndex: number - ) => { - // Proceed only if left click - if (event.button !== 0) return - - if (!selectedTool) { - return - } - - const { x, y } = getPointerCoordinates(event) - - const newField: DrawnField = { - left: to(page.width, x), - top: to(page.width, y), - width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width, - height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height, - counterpart: getAvailableSigner(lastSigner, defaultSignerNpub), - type: selectedTool.identifier - } - - page.drawnFields.push(newField) - - setActiveDrawnField({ - fileIndex, - pageIndex, - drawnFieldIndex: page.drawnFields.length - 1 - }) - setMouseState((prev) => { - return { - ...prev, - clicked: true - } - }) - } - - /** - * Drawing is finished, resets all the variables used to draw - * @param event Pointer event - */ - const handlePointerUp = () => { - setMouseState((prev) => { - return { - ...prev, - clicked: false, - dragging: false, - resizing: false - } - }) - } - - /** - * After {@link handlePointerDown} create an drawing element, this function gets called on every pixel moved - * which alters the newly created drawing element, resizing it while pointer moves - * @param event Pointer event - * @param page PdfPage where moving is happening - */ - const handlePointerMove = (event: React.PointerEvent, page: PdfPage) => { - if (mouseState.clicked && selectedTool && event.pointerType === 'mouse') { - const lastElementIndex = page.drawnFields.length - 1 - - const lastDrawnField = page.drawnFields[lastElementIndex] - - // Return early if we don't have lastDrawnField - // Issue noticed in the console when dragging out of bounds - // to the page below (without releaseing mouse click) - if (!lastDrawnField) return - - const { x, y } = getPointerCoordinates(event) - - const width = to(page.width, x) - lastDrawnField.left - const height = to(page.width, y) - lastDrawnField.top - - lastDrawnField.width = width - lastDrawnField.height = height - - const currentDrawnFields = page.drawnFields - - currentDrawnFields[lastElementIndex] = lastDrawnField - - refreshPdfFiles() - } - } - - /** - * Fired when event happens on the drawn element which will be moved - * pointer coordinates relative to drawn element will be stored - * so when we start moving, offset can be calculated - * x - offsetX - * y - offsetY - * - * @param event Pointer event - * @param drawnFieldIndex Which we are moving - */ - const handleDrawnFieldPointerDown = ( - event: React.PointerEvent, - fileIndex: number, - pageIndex: number, - drawnFieldIndex: number - ) => { - event.stopPropagation() - - // Proceed only if left click - if (event.button !== 0) return - - const drawingRectangleCoords = getPointerCoordinates(event) - - setActiveDrawnField({ fileIndex, pageIndex, drawnFieldIndex }) - setMouseState({ - dragging: true, - clicked: false, - coordsInWrapper: { - x: drawingRectangleCoords.x, - y: drawingRectangleCoords.y - } - }) - } - - /** - * Moves the drawnElement by the pointer position (pointer can grab anywhere on the drawn element) - * @param event Pointer event - * @param drawnField which we are moving - * @param pageWidth pdf value which is used to calculate scaled offset - */ - const handleDrawnFieldPointerMove = ( - event: React.PointerEvent, - drawnField: DrawnField, - pageWidth: number - ) => { - if (mouseState.dragging) { - const { x, y, rect } = getPointerCoordinates( - event, - event.currentTarget.parentElement - ) - const coordsOffset = mouseState.coordsInWrapper - - if (coordsOffset) { - let left = to(pageWidth, x - coordsOffset.x) - let top = to(pageWidth, y - coordsOffset.y) - - const rightLimit = to(pageWidth, rect.width) - drawnField.width - const bottomLimit = to(pageWidth, rect.height) - drawnField.height - - if (left < 0) left = 0 - if (top < 0) top = 0 - if (left > rightLimit) left = rightLimit - if (top > bottomLimit) top = bottomLimit - - drawnField.left = left - drawnField.top = top - - refreshPdfFiles() - } - } - } - - /** - * Fired when clicked on the resize handle, sets the state for a resize action - * @param event Pointer event - * @param drawnFieldIndex which we are resizing - */ - const handleResizePointerDown = ( - event: React.PointerEvent, - fileIndex: number, - pageIndex: number, - drawnFieldIndex: number - ) => { - // Proceed only if left click - if (event.button !== 0) return - event.stopPropagation() - - setActiveDrawnField({ fileIndex, pageIndex, drawnFieldIndex }) - setMouseState({ - resizing: true - }) - } - - /** - * Resizes the drawn element by the mouse position - * @param event Pointer event - * @param drawnField which we are resizing - * @param pageWidth pdf value which is used to calculate scaled offset - */ - const handleResizePointerMove = ( - event: React.PointerEvent, - drawnField: DrawnField, - pageWidth: number - ) => { - if (mouseState.resizing) { - const { x, y } = getPointerCoordinates( - event, - // currentTarget = span handle - // 1st parent = drawnField - // 2nd parent = img - event.currentTarget.parentElement?.parentElement - ) - - const width = to(pageWidth, x) - drawnField.left - const height = to(pageWidth, y) - drawnField.top - - drawnField.width = width - drawnField.height = height - - refreshPdfFiles() - } - } - - /** - * Removes the drawn element using the indexes in the params - * @param event Pointer event - * @param pdfFileIndex pdf file index - * @param pdfPageIndex pdf page index - * @param drawnFileIndex drawn file index - */ - const handleRemovePointerDown = ( - event: React.PointerEvent, - pdfFileIndex: number, - pdfPageIndex: number, - drawnFileIndex: number - ) => { - event.stopPropagation() - - const pages = sigitFiles[pdfFileIndex]?.pages - if (pages) { - pages[pdfPageIndex]?.drawnFields?.splice(drawnFileIndex, 1) - } - } - - /** - * Used to stop pointer click propagating to the parent elements - * so select can work properly - * @param event Pointer event - */ - const handleUserSelectPointerDown = (event: React.PointerEvent) => { - event.stopPropagation() - } + lastIndexer && + lastIndexer[0] === fileIndex && + lastIndexer[1] === pageIndex && + lastIndexer[2] === drawnFieldIndex /** * Gets the pointer coordinates relative to a element in the `event` param @@ -352,8 +112,8 @@ export const DrawPDFFields = (props: Props) => { const rect = target.getBoundingClientRect() // Clamp X Y within the target - const x = Math.min(event.clientX, rect.right) - rect.left //x position within the element. - const y = Math.min(event.clientY, rect.bottom) - rect.top //y position within the element. + const x = Math.max(0, Math.min(event.clientX, rect.right) - rect.left) //x position within the element. + const y = Math.max(0, Math.min(event.clientY, rect.bottom) - rect.top) //y position within the element. return { x, @@ -361,6 +121,347 @@ export const DrawPDFFields = (props: Props) => { rect } } + + /** + * Fired only on when left (primary pointer interaction) clicking page image + * Creates new drawnElement + * + * @param event Pointer event + * @param pageIndexer File and page index + * @param pageWidth pdf value used to scale pointer coordinates + */ + const handlePointerDown = useCallback( + ( + event: React.PointerEvent, + pageIndexer: PageIndexer, + pageWidth: number + ) => { + // Proceed only if left click + if (event.button !== 0) return + if (!selectedTool) return + event.currentTarget.setPointerCapture(event.pointerId) + const counterpart = getAvailableSigner(lastSigner, defaultSignerNpub) + const { x, y } = getPointerCoordinates(event) + + setIndexer(pageIndexer) + setField({ + x: to(pageWidth, x), + y: to(pageWidth, y), + left: to(pageWidth, x), + top: to(pageWidth, y), + width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width, + height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height, + type: selectedTool.identifier, + counterpart + }) + setMouseState({ + clicked: true + }) + }, + [defaultSignerNpub, getAvailableSigner, lastSigner, selectedTool, to] + ) + + /** + * After {@link handlePointerDown} creates an drawing element, this function + * alters the newly created drawing element, resizing it while pointer moves + * @param event Pointer event + * @param pageWidth pdf value used to scale pointer coordinates + */ + const handlePointerMove = useCallback( + (event: React.PointerEvent, pageWidth: number) => { + if (mouseState.clicked && selectedTool && event.pointerType === 'mouse') { + const { x, y } = getPointerCoordinates(event) + const pageX = to(pageWidth, x) + const pageY = to(pageWidth, y) + + // Calculate left, top, width, and height based on direction + setField((prev) => { + const left = pageX < prev!.x ? pageX : prev!.x + const top = pageY < prev!.y ? pageY : prev!.y + + const width = Math.abs(pageX - prev!.x) + const height = Math.abs(pageY - prev!.y) + return { ...prev!, left, top, width, height } + }) + } + }, + [mouseState.clicked, selectedTool, to] + ) + + /** + * Fired when event happens on the drawn element which will be moved + * pointer coordinates relative to drawn element will be stored + * so when we start moving, offset can be calculated + * x - offsetX + * y - offsetY + * + * @param event Pointer event + * @param fieldIndexer Which field we are moving + */ + const handleDrawnFieldPointerDown = ( + event: React.PointerEvent, + fieldIndexer: FieldIndexer + ) => { + event.stopPropagation() + + // Proceed only if left click + if (event.button !== 0) return + + event.currentTarget.setPointerCapture(event.pointerId) + const drawingRectangleCoords = getPointerCoordinates(event) + const [fileIndex, pageIndex, drawnFieldIndex] = fieldIndexer + const page = sigitFiles[fileIndex].pages![pageIndex] + const drawnField = page.drawnFields[drawnFieldIndex] + + setIndexer(fieldIndexer) + setField({ + ...drawnField, + x: to(page.width, drawingRectangleCoords.x), + y: to(page.width, drawingRectangleCoords.y) + }) + setLastIndexer(fieldIndexer) + setMouseState({ + dragging: true, + clicked: false, + coordsInWrapper: { + x: drawingRectangleCoords.x, + y: drawingRectangleCoords.y + } + }) + + // Make signers dropdown visible + setHideSignersForDrawnField((prev) => ({ + ...prev, + [drawnFieldIndex]: false + })) + } + + /** + * Moves the drawnElement by the pointer position (pointer can grab anywhere on the drawn element) + * @param event Pointer event + * @param pageWidth pdf value used to scale pointer coordinates + */ + const handleDrawnFieldPointerMove = ( + event: React.PointerEvent, + pageWidth: number + ) => { + if (mouseState.dragging) { + const { x, y, rect } = getPointerCoordinates( + event, + event.currentTarget.parentElement + ) + const coordsOffset = mouseState.coordsInWrapper + + if (coordsOffset) { + let left = to(pageWidth, x - coordsOffset.x) + let top = to(pageWidth, y - coordsOffset.y) + + setField((prev) => { + const rightLimit = to(pageWidth, rect.width) - prev!.width + const bottomLimit = to(pageWidth, rect.height) - prev!.height + + if (left < 0) left = 0 + if (top < 0) top = 0 + if (left > rightLimit) left = rightLimit + if (top > bottomLimit) top = bottomLimit + + return { + ...prev!, + left, + top + } + }) + } + } + } + + /** + * Fired when clicked on the resize handle, sets the state for a resize action + * @param event Pointer event + * @param fieldIndexer which field we are resizing + */ + const handleResizePointerDown = useCallback( + (event: React.PointerEvent, fieldIndexer: FieldIndexer) => { + // Proceed only if left click + if (event.button !== 0) return + event.stopPropagation() + + event.currentTarget.setPointerCapture(event.pointerId) + const [fileIndex, pageIndex, drawnFieldIndex] = fieldIndexer + const page = sigitFiles[fileIndex].pages![pageIndex] + const drawnField = page.drawnFields[drawnFieldIndex] + setIndexer(fieldIndexer) + setField({ + ...drawnField, + x: drawnField.left, + y: drawnField.top + }) + setLastIndexer(fieldIndexer) + setMouseState({ + resizing: true + }) + }, + [sigitFiles] + ) + + /** + * Resizes the drawn element by the mouse position + * @param event Pointer event + * @param pageWidth pdf value used to scale pointer coordinates + */ + const handleResizePointerMove = useCallback( + (event: React.PointerEvent, pageWidth: number) => { + if (mouseState.resizing) { + // currentTarget = span handle + // 1st parent = drawnField + // 2nd parent = img + const { x, y } = getPointerCoordinates( + event, + event.currentTarget.parentElement?.parentElement + ) + + const pageX = to(pageWidth, x) + const pageY = to(pageWidth, y) + + setField((prev) => { + const left = pageX < prev!.x ? pageX : prev!.x + const top = pageY < prev!.y ? pageY : prev!.y + + const width = Math.abs(pageX - prev!.x) + const height = Math.abs(pageY - prev!.y) + return { ...prev!, left, top, width, height } + }) + } + }, + [mouseState.resizing, to] + ) + + const handlePointerUpReleaseCapture = useCallback( + (event: React.PointerEvent) => { + event.currentTarget.releasePointerCapture(event.pointerId) + }, + [] + ) + + /** + * Removes the drawn element using the indexes in the params + * @param event Pointer event + * @param fieldIIndexer [file index, page index, field index] + */ + const handleRemovePointerDown = ( + event: React.PointerEvent, + [fileIndex, pageIndex, fieldIndex]: FieldIndexer + ) => { + event.stopPropagation() + + updateSigitFiles((draft) => { + draft[fileIndex]?.pages![pageIndex]?.drawnFields?.splice(fieldIndex, 1) + }) + } + + /** + * Used to stop pointer click propagating to the parent elements + * so select can work properly + * @param event Pointer event + */ + const handleUserSelectPointerDown = (event: React.PointerEvent) => { + event.stopPropagation() + } + + /** + * Handles Escape button-down event and hides all signers dropdowns + * @param event SyntheticEvent event + */ + const handleEscapeButtonDown = (event: React.SyntheticEvent) => { + // get native event + const { nativeEvent } = event + + //check if event is a keyboard event + if (nativeEvent instanceof KeyboardEvent) { + // check if event code is Escape + if (nativeEvent.code === KeyboardCode.Escape) { + // hide all signers dropdowns + const newHideSignersForDrawnField: HideSignersForDrawnField = {} + + Object.keys(hideSignersForDrawnField).forEach((key) => { + // Object.keys always returns an array of strings, + // that is why unknown type is used below + newHideSignersForDrawnField[key as unknown as number] = true + }) + + setHideSignersForDrawnField(newHideSignersForDrawnField) + } + } + } + + /** + * Drawing is finished, resets all the variables used to draw + */ + const handlePointerUp = useCallback(() => { + // Proceed if we have selected something + if (indexer) { + // Check if we have the "preview" field state + if (field) { + // Cancel update if preview field is below the MINIMUM_RECT_SIZE threshhold + if ( + field.width < MINIMUM_RECT_SIZE.width || + field.height < MINIMUM_RECT_SIZE.height + ) { + setIndexer(undefined) + setMouseState({}) + return + } + + const [fileIndex, pageIndex, fieldIndex] = indexer + + // Add new drawn field to the files + if (mouseState.clicked) { + updateSigitFiles((draft) => { + draft[fileIndex].pages![pageIndex].drawnFields.push(field) + }) + } + + // Move + if (mouseState.dragging) { + updateSigitFiles((draft) => { + draft[fileIndex].pages![pageIndex].drawnFields[fieldIndex!] = field + }) + } + + // Resize + if (mouseState.resizing) { + updateSigitFiles((draft) => { + draft[fileIndex].pages![pageIndex].drawnFields[fieldIndex!] = field + }) + } + + // Clear indexer after applying the update + setIndexer(undefined) + } + } + setMouseState({}) + }, [ + field, + indexer, + mouseState.clicked, + mouseState.dragging, + mouseState.resizing, + updateSigitFiles + ]) + + /** + * Drawing events + */ + useEffect(() => { + window.addEventListener('pointerup', handlePointerUp) + window.addEventListener('pointercancel', handlePointerUp) + + return () => { + window.removeEventListener('pointerup', handlePointerUp) + window.removeEventListener('pointercancel', handlePointerUp) + } + }, [handlePointerUp]) + /** * Renders the pdf pages and drawing elements */ @@ -371,38 +472,83 @@ export const DrawPDFFields = (props: Props) => { return ( <> {file.pages?.map((page, pageIndex: number) => { + let isPageIndexerActive = false + if (indexer) { + const [fi, pi, di] = indexer + isPageIndexerActive = + fi === fileIndex && pi === pageIndex && typeof di === 'undefined' + } + return (
handleEscapeButtonDown(event)} > { - handlePointerMove(event, page) - }} onPointerDown={(event) => { - handlePointerDown(event, page, fileIndex, pageIndex) + handlePointerDown(event, [fileIndex, pageIndex], page.width) }} + onPointerMove={(event) => { + handlePointerMove(event, page.width) + }} + onPointerUp={handlePointerUpReleaseCapture} draggable="false" src={page.image} alt={`page ${pageIndex + 1} of ${file.name}`} /> - + {isPageIndexerActive && field && ( +
+
+ {getToolboxLabelByMarkType(field.type) || 'placeholder'} +
+
+ )} {page.drawnFields.map((drawnField, drawnFieldIndex: number) => { + let isFieldIndexerActive = false + if (indexer) { + const [fi, pi, di] = indexer + isFieldIndexerActive = + fi === fileIndex && + pi === pageIndex && + di === drawnFieldIndex + } + return (
- handleDrawnFieldPointerDown( - event, + handleDrawnFieldPointerDown(event, [ fileIndex, pageIndex, drawnFieldIndex - ) + ]) } onPointerMove={(event) => { - handleDrawnFieldPointerMove(event, drawnField, page.width) + handleDrawnFieldPointerMove(event, page.width) }} + onPointerUp={handlePointerUpReleaseCapture} className={styles.drawingRectangle} style={{ backgroundColor: drawnField.counterpart @@ -411,12 +557,29 @@ export const DrawPDFFields = (props: Props) => { outlineColor: drawnField.counterpart ? `#${npubToHex(drawnField.counterpart)?.substring(0, 6)}` : undefined, - left: inPx(from(page.width, drawnField.left)), - top: inPx(from(page.width, drawnField.top)), - width: inPx(from(page.width, drawnField.width)), - height: inPx(from(page.width, drawnField.height)), + ...(isFieldIndexerActive && field + ? { + left: inPx(from(page.width, field.left)), + top: inPx(from(page.width, field.top)), + width: inPx(from(page.width, field.width)), + height: inPx(from(page.width, field.height)) + } + : { + left: inPx(from(page.width, drawnField.left)), + top: inPx(from(page.width, drawnField.top)), + width: inPx(from(page.width, drawnField.width)), + height: inPx(from(page.width, drawnField.height)) + }), + pointerEvents: mouseState.clicked ? 'none' : 'all', touchAction: 'none', + zIndex: isActiveDrawnField( + fileIndex, + pageIndex, + drawnFieldIndex + ) + ? 60 + : undefined, opacity: mouseState.dragging && isActiveDrawnField( @@ -440,37 +603,36 @@ export const DrawPDFFields = (props: Props) => {
- handleResizePointerDown( - event, + handleResizePointerDown(event, [ fileIndex, pageIndex, drawnFieldIndex - ) + ]) } onPointerMove={(event) => { - handleResizePointerMove(event, drawnField, page.width) + handleResizePointerMove(event, page.width) }} + onPointerUp={handlePointerUpReleaseCapture} className={styles.resizeHandle} style={{ - background: - mouseState.resizing && + ...(mouseState.resizing && isActiveDrawnField( fileIndex, pageIndex, drawnFieldIndex - ) - ? 'var(--primary-main)' - : undefined + ) && { + cursor: 'grabbing', + opacity: 0.1 + }) }} > { - handleRemovePointerDown( - event, + handleRemovePointerDown(event, [ fileIndex, pageIndex, drawnFieldIndex - ) + ]) }} className={styles.removeHandle} > @@ -492,62 +654,81 @@ export const DrawPDFFields = (props: Props) => { fileIndex, pageIndex, drawnFieldIndex - ) && ( -
- - Counterpart - { + drawnField.counterpart = event.target.value + setLastSigner(event.target.value) + }} + labelId="counterparts" + label="Counterparts" + sx={{ + background: 'white' + }} + renderValue={(value) => ( + + )} + > + {signers.map((signer, index) => { + const npub = hexToNpub(signer.pubkey) + const profile = userProfiles[signer.pubkey] + const displayValue = getProfileUsername( + npub, + profile + ) + // make current signers dropdown visible + if ( + hideSignersForDrawnField[drawnFieldIndex] === + undefined || + hideSignersForDrawnField[drawnFieldIndex] === + true + ) { + setHideSignersForDrawnField((prev) => ({ + ...prev, + [drawnFieldIndex]: false + })) + } - return ( - - - img': { - width: '30px', - height: '30px' - } - }} - /> - - {displayValue} - - ) - })} - - -
- )} + return ( + + + img': { + width: '30px', + height: '30px' + } + }} + /> + + {displayValue} + + ) + })} + + +
+ )}
) })} @@ -558,58 +739,24 @@ export const DrawPDFFields = (props: Props) => { ) } - const renderCounterpartValue = (npub: string) => { - let displayValue = _.truncate(npub, { length: 16 }) - - const signer = signers.find((u) => u.pubkey === npubToHex(npub)) - if (signer) { - const metadata = props.metadata[signer.pubkey] - displayValue = getProfileUsername(npub, metadata) - - return ( -
- img': { - width: '21px', - height: '21px' - } - }} - /> - {displayValue} -
- ) - } - - return displayValue - } - return (
- {sigitFiles.map((file, i) => { - return ( - -
- {file.isPdf && getPdfPages(file, i)} - {file.isImage && ( - {file.name} - )} - {!(file.isPdf || file.isImage) && ( - - )} -
- {i < sigitFiles.length - 1 && } -
- ) - })} + {sigitFiles.length > 0 && + sigitFiles + .map((file, i) => + file.isPdf ? ( + + {getPdfPages(file, i)} + + ) : ( + + ) + ) + .reduce((prev, curr, i) => [ + prev, + , + curr + ])}
) } diff --git a/src/components/DrawPDFFields/internal/Counterpart.module.scss b/src/components/DrawPDFFields/internal/Counterpart.module.scss new file mode 100644 index 0000000..933913e --- /dev/null +++ b/src/components/DrawPDFFields/internal/Counterpart.module.scss @@ -0,0 +1,3 @@ +.counterpartSelectValue { + display: flex; +} diff --git a/src/components/DrawPDFFields/internal/Counterpart.tsx b/src/components/DrawPDFFields/internal/Counterpart.tsx new file mode 100644 index 0000000..508792d --- /dev/null +++ b/src/components/DrawPDFFields/internal/Counterpart.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import { User } from '../../../types' +import _ from 'lodash' +import { npubToHex, getProfileUsername } from '../../../utils' +import { AvatarIconButton } from '../../UserAvatarIconButton' +import styles from './Counterpart.module.scss' +import { NDKUserProfile } from '@nostr-dev-kit/ndk' + +interface CounterpartProps { + npub: string + userProfiles: { + [key: string]: NDKUserProfile + } + signers: User[] +} + +export const Counterpart = React.memo( + ({ npub, userProfiles, signers }: CounterpartProps) => { + let displayValue = _.truncate(npub, { length: 16 }) + + const signer = signers.find((u) => u.pubkey === npubToHex(npub)) + if (signer) { + const profile = userProfiles[signer.pubkey] + displayValue = getProfileUsername(npub, profile) + + return ( +
+ img': { + width: '21px', + height: '21px' + } + }} + /> + {displayValue} +
+ ) + } + + return displayValue + } +) diff --git a/src/components/DrawPDFFields/internal/FileItem.tsx b/src/components/DrawPDFFields/internal/FileItem.tsx new file mode 100644 index 0000000..a1f13ea --- /dev/null +++ b/src/components/DrawPDFFields/internal/FileItem.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import { SigitFile } from '../../../utils/file' +import { ExtensionFileBox } from '../../ExtensionFileBox' +import { ImageItem } from './ImageItem' + +interface FileItemProps { + file: SigitFile +} + +export const FileItem = React.memo(({ file }: FileItemProps) => { + const content = + if (file.isImage) return + + return ( +
+ {content} +
+ ) +}) diff --git a/src/components/DrawPDFFields/internal/ImageItem.tsx b/src/components/DrawPDFFields/internal/ImageItem.tsx new file mode 100644 index 0000000..8cba790 --- /dev/null +++ b/src/components/DrawPDFFields/internal/ImageItem.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import { SigitFile } from '../../../utils/file' + +interface ImageItemProps { + file: SigitFile +} + +export const ImageItem = React.memo(({ file }: ImageItemProps) => { + return {file.name} +}) diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss index 15661e0..5eb5307 100644 --- a/src/components/DrawPDFFields/style.module.scss +++ b/src/components/DrawPDFFields/style.module.scss @@ -13,6 +13,10 @@ } } +.pdfImageWrapper:focus { + outline: none; +} + .placeholder { position: absolute; opacity: 0.5; @@ -34,10 +38,6 @@ visibility: hidden; } - &.edited { - outline: 1px dotted #01aaad; - } - .resizeHandle { position: absolute; right: -5px; @@ -47,7 +47,7 @@ background-color: #fff; border: 1px solid rgb(160, 160, 160); border-radius: 50%; - cursor: nwse-resize; + cursor: grab; // Increase the area a bit so it's easier to click &::after { @@ -85,13 +85,34 @@ } } -.counterpartSelectValue { - display: flex; -} - .counterpartAvatar { img { width: 21px; height: 21px; } } + +.signingRectangle { + position: absolute; + outline: 1px solid #01aaad; + z-index: 40; + background-color: #01aaad4b; + cursor: pointer; + + &.edited { + outline: 1px dotted #01aaad; + } +} + +.drawingRectanglePreview { + position: absolute; + outline: 1px solid; + z-index: 50; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + pointer-events: none; + touch-action: none; + opacity: 0.8; +} diff --git a/src/components/FileList/index.tsx b/src/components/FileList/index.tsx index a47ace7..62f3119 100644 --- a/src/components/FileList/index.tsx +++ b/src/components/FileList/index.tsx @@ -1,23 +1,29 @@ +import React from 'react' +import { Button, Menu, MenuItem } from '@mui/material' +import PopupState, { bindTrigger, bindMenu } from 'material-ui-popup-state' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { + faCheck, + faLock, + faTriangleExclamation +} from '@fortawesome/free-solid-svg-icons' import { CurrentUserFile } from '../../types/file.ts' import styles from './style.module.scss' -import { Button } from '@mui/material' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCheck } from '@fortawesome/free-solid-svg-icons' interface FileListProps { files: CurrentUserFile[] currentFile: CurrentUserFile setCurrentFile: (file: CurrentUserFile) => void - handleDownload: () => void - downloadLabel?: string + handleExport?: () => void + handleEncryptedExport?: () => void } const FileList = ({ files, currentFile, setCurrentFile, - handleDownload, - downloadLabel + handleExport, + handleEncryptedExport }: FileListProps) => { const isActive = (file: CurrentUserFile) => file.id === currentFile.id return ( @@ -42,9 +48,49 @@ const FileList = ({ ))} - + + {(typeof handleExport === 'function' || + typeof handleEncryptedExport === 'function') && ( + + {(popupState) => ( + + + + {typeof handleEncryptedExport === 'function' && ( + { + popupState.close + handleEncryptedExport() + }} + > + +   ENCRYPTED + + )} + {typeof handleExport === 'function' && ( + { + popupState.close + handleExport() + }} + > + +   UNENCRYPTED + + )} + + + )} + + )}
) } diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx index ead7cec..c7459e3 100644 --- a/src/components/Footer/Footer.tsx +++ b/src/components/Footer/Footer.tsx @@ -68,6 +68,12 @@ export const Footer = () => }} component={Link} to={'/'} + onClick={(event) => { + if (['', '#/'].includes(window.location.hash)) { + event.preventDefault() + window.scrollTo(0, 0) + } + }} variant={'text'} > Home diff --git a/src/components/LoadingSpinner/style.module.scss b/src/components/LoadingSpinner/style.module.scss index 088f389..2ed8093 100644 --- a/src/components/LoadingSpinner/style.module.scss +++ b/src/components/LoadingSpinner/style.module.scss @@ -7,7 +7,7 @@ align-items: center; justify-content: center; background-color: rgba(0, 0, 0, 0.5); - z-index: 50; + z-index: 70; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); } diff --git a/src/components/MarkFormField/index.tsx b/src/components/MarkFormField/index.tsx index 9a14989..43c94a9 100644 --- a/src/components/MarkFormField/index.tsx +++ b/src/components/MarkFormField/index.tsx @@ -1,5 +1,4 @@ import { CurrentUserMark } from '../../types/mark.ts' -import styles from './style.module.scss' import { findNextIncompleteCurrentUserMark, getToolboxLabelByMarkType, @@ -7,15 +6,22 @@ import { isCurrentValueLast } from '../../utils' import React, { useState } from 'react' +import { MarkInput } from '../MarkTypeStrategy/MarkInput.tsx' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCheck, faDownload } from '@fortawesome/free-solid-svg-icons' +import { Button } from '@mui/material' +import styles from './style.module.scss' +import { ButtonUnderline } from '../ButtonUnderline/index.tsx' interface MarkFormFieldProps { currentUserMarks: CurrentUserMark[] handleCurrentUserMarkChange: (mark: CurrentUserMark) => void - handleSelectedMarkValueChange: ( - event: React.ChangeEvent + handleSelectedMarkValueChange: (value: string) => void + handleSubmit: ( + event: React.MouseEvent, + type: 'online' | 'offline' ) => void - handleSubmit: (event: React.FormEvent) => void - selectedMark: CurrentUserMark + selectedMark: CurrentUserMark | null selectedMarkValue: string } @@ -31,28 +37,52 @@ const MarkFormField = ({ handleCurrentUserMarkChange }: MarkFormFieldProps) => { const [displayActions, setDisplayActions] = useState(true) + const [complete, setComplete] = useState(false) const isReadyToSign = () => isCurrentUserMarksComplete(currentUserMarks) || isCurrentValueLast(currentUserMarks, selectedMark, selectedMarkValue) const isCurrent = (currentMark: CurrentUserMark) => - currentMark.id === selectedMark.id + currentMark.id === selectedMark?.id && !complete const isDone = (currentMark: CurrentUserMark) => isCurrent(currentMark) ? !!selectedMarkValue : currentMark.isCompleted const findNext = () => { return ( - currentUserMarks[selectedMark.id] || + currentUserMarks[selectedMark!.id] || findNextIncompleteCurrentUserMark(currentUserMarks) ) } const handleFormSubmit = (event: React.FormEvent) => { event.preventDefault() - console.log('handle form submit runs...') - return isReadyToSign() - ? handleSubmit(event) - : handleCurrentUserMarkChange(findNext()!) + // Without this line, we lose mark values when switching + handleCurrentUserMarkChange(selectedMark!) + + if (!complete) { + isReadyToSign() + ? setComplete(true) + : handleCurrentUserMarkChange(findNext()!) + } } + const toggleActions = () => setDisplayActions(!displayActions) - const markLabel = getToolboxLabelByMarkType(selectedMark.mark.type) + const markLabel = selectedMark + ? getToolboxLabelByMarkType(selectedMark.mark.type) + : '' + const handleCurrentUserMarkClick = (mark: CurrentUserMark) => { + setComplete(false) + handleCurrentUserMarkChange(mark) + } + + const handleSelectCompleteMark = () => { + if (currentUserMarks.length) handleCurrentUserMarkChange(selectedMark!) + setComplete(true) + } + + const handleSignAndComplete = + (type: 'online' | 'offline') => + (event: React.MouseEvent) => { + handleSubmit(event, type) + } + return (
@@ -78,31 +108,64 @@ const MarkFormField = ({
-

Add {markLabel}

+ {!complete && selectedMark ? ( +

Add {markLabel}

+ ) : ( +

Finish

+ )}
-
handleFormSubmit(e)}> - -
- -
-
+ {!complete && selectedMark ? ( +
handleFormSubmit(e)}> + +
+ +
+ + ) : ( + <> +
+ +
+ + + Sign and export locally instead + + + )} +
{currentUserMarks.map((mark, index) => { return (
@@ -112,6 +175,22 @@ const MarkFormField = ({
) })} +
+ + {complete && ( +
+ )} +
diff --git a/src/components/MarkFormField/style.module.scss b/src/components/MarkFormField/style.module.scss index 0125140..e7a3e3c 100644 --- a/src/components/MarkFormField/style.module.scss +++ b/src/components/MarkFormField/style.module.scss @@ -70,6 +70,11 @@ margin-top: 10px; } + .completeButton { + font-size: 18px; + padding: 10px 20px; + } + .paginationButton { font-size: 12px; padding: 5px 10px; @@ -78,7 +83,8 @@ color: rgba(0, 0, 0, 0.5); } - .paginationButton:hover { + .paginationButton:hover, + .paginationButton:focus { background: #447592; color: rgba(255, 255, 255, 0.5); } @@ -122,7 +128,7 @@ align-items: center; grid-gap: 15px; box-shadow: 0 -2px 4px 0 rgb(0, 0, 0, 0.1); - max-width: 750px; + max-width: 450px; &.expanded { display: flex; @@ -216,3 +222,7 @@ flex-direction: column; grid-gap: 5px; } + +.finishPage { + padding: 1px 0; +} diff --git a/src/components/MarkTypeStrategy/MarkInput.tsx b/src/components/MarkTypeStrategy/MarkInput.tsx new file mode 100644 index 0000000..382d9be --- /dev/null +++ b/src/components/MarkTypeStrategy/MarkInput.tsx @@ -0,0 +1,16 @@ +import { MarkType } from '../../types/drawing' +import { MARK_TYPE_CONFIG, MarkInputProps } from './MarkStrategy' + +interface MarkInputComponentProps extends MarkInputProps { + markType: MarkType +} + +export const MarkInput = ({ markType, ...rest }: MarkInputComponentProps) => { + const { input: InputComponent } = MARK_TYPE_CONFIG[markType] || {} + + if (typeof InputComponent !== 'undefined') { + return + } + + return null +} diff --git a/src/components/MarkTypeStrategy/MarkRender.tsx b/src/components/MarkTypeStrategy/MarkRender.tsx new file mode 100644 index 0000000..1d5117c --- /dev/null +++ b/src/components/MarkTypeStrategy/MarkRender.tsx @@ -0,0 +1,20 @@ +import { MarkType } from '../../types/drawing' +import { MARK_TYPE_CONFIG, MarkRenderProps } from './MarkStrategy' + +interface MarkRenderComponentProps extends MarkRenderProps { + markType: MarkType +} + +export const MarkRender = ({ markType, ...rest }: MarkRenderComponentProps) => { + const { render: RenderComponent } = MARK_TYPE_CONFIG[markType] || {} + + if (typeof RenderComponent !== 'undefined') { + return + } + + return +} + +const DefaultRenderComponent = ({ value }: MarkRenderProps) => ( + {value} +) diff --git a/src/components/MarkTypeStrategy/MarkStrategy.tsx b/src/components/MarkTypeStrategy/MarkStrategy.tsx new file mode 100644 index 0000000..562302e --- /dev/null +++ b/src/components/MarkTypeStrategy/MarkStrategy.tsx @@ -0,0 +1,32 @@ +import { MarkType } from '../../types/drawing' +import { CurrentUserMark, Mark } from '../../types/mark' +import { TextStrategy } from './Text' +import { SignatureStrategy } from './Signature' + +export interface MarkInputProps { + value: string + handler: (value: string) => void + placeholder?: string + userMark?: CurrentUserMark +} + +export interface MarkRenderProps { + value?: string + mark: Mark +} + +export interface MarkStrategy { + input: React.FC + render: React.FC + encryptAndUpload?: (value: string, key?: string) => Promise + fetchAndDecrypt?: (value: string, key?: string) => Promise +} + +export type MarkStrategies = { + [key in MarkType]?: MarkStrategy +} + +export const MARK_TYPE_CONFIG: MarkStrategies = { + [MarkType.TEXT]: TextStrategy, + [MarkType.SIGNATURE]: SignatureStrategy +} diff --git a/src/components/MarkTypeStrategy/Signature/Input.module.scss b/src/components/MarkTypeStrategy/Signature/Input.module.scss new file mode 100644 index 0000000..74ce0e0 --- /dev/null +++ b/src/components/MarkTypeStrategy/Signature/Input.module.scss @@ -0,0 +1,44 @@ +@import '../../../styles/colors.scss'; + +$padding: 5px; + +.wrapper { + display: flex; + justify-content: center; + align-items: center; + padding: $padding; +} + +.relative { + position: relative; + outline: 1px solid black; +} + +.canvas { + background-color: $body-background-color; + cursor: crosshair; + + // Disable panning/zooming when touching canvas element + -ms-touch-action: none; + touch-action: none; + -webkit-user-select: none; + user-select: none; +} + +.absolute { + position: absolute; + inset: 0; + pointer-events: none; +} + +.reset { + cursor: pointer; + position: absolute; + top: 0; + right: $padding; + color: $primary-main; + + &:hover { + color: $primary-dark; + } +} diff --git a/src/components/MarkTypeStrategy/Signature/Input.tsx b/src/components/MarkTypeStrategy/Signature/Input.tsx new file mode 100644 index 0000000..71777f3 --- /dev/null +++ b/src/components/MarkTypeStrategy/Signature/Input.tsx @@ -0,0 +1,101 @@ +import { useCallback, useEffect, useRef } from 'react' +import { faEraser } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { MarkRenderSignature } from './Render' +import SignaturePad from 'signature_pad' +import { SIGNATURE_PAD_OPTIONS, SIGNATURE_PAD_SIZE } from '../../../utils/const' +import { BasicPoint } from 'signature_pad/dist/types/point' +import { MarkInputProps } from '../MarkStrategy' +import styles from './Input.module.scss' + +export const MarkInputSignature = ({ + value, + handler, + userMark +}: MarkInputProps) => { + const canvasRef = useRef(null) + const signaturePad = useRef(null) + + const update = useCallback(() => { + const data = signaturePad.current?.toData() + const reduced = data?.map((pg) => pg.points) + const json = JSON.stringify(reduced) + + if (signaturePad.current && !signaturePad.current?.isEmpty()) { + handler(json) + } else { + handler('') + } + }, [handler]) + + useEffect(() => { + const handleEndStroke = () => { + update() + } + if (canvasRef.current) { + if (signaturePad.current === null) { + signaturePad.current = new SignaturePad( + canvasRef.current, + SIGNATURE_PAD_OPTIONS + ) + } + + signaturePad.current.addEventListener('endStroke', handleEndStroke) + } + + return () => { + window.removeEventListener('endStroke', handleEndStroke) + } + }, [update]) + + useEffect(() => { + if (signaturePad.current) { + if (value) { + signaturePad.current.fromData( + JSON.parse(value).map((p: BasicPoint[]) => ({ + points: p + })) + ) + } else { + signaturePad.current?.clear() + } + } + update() + }, [update, value]) + + const handleReset = () => { + signaturePad.current?.clear() + update() + } + + return ( +
+
+ + {typeof userMark?.mark !== 'undefined' && ( +
+ +
+ )} +
+ +
+
+
+ ) +} diff --git a/src/components/MarkTypeStrategy/Signature/Render.module.scss b/src/components/MarkTypeStrategy/Signature/Render.module.scss new file mode 100644 index 0000000..d09d6d2 --- /dev/null +++ b/src/components/MarkTypeStrategy/Signature/Render.module.scss @@ -0,0 +1,9 @@ +.img { + width: 100%; + height: 100%; + object-fit: contain; + overflow: hidden; + pointer-events: none; + -webkit-user-select: none; + user-select: none; +} diff --git a/src/components/MarkTypeStrategy/Signature/Render.tsx b/src/components/MarkTypeStrategy/Signature/Render.tsx new file mode 100644 index 0000000..4f47527 --- /dev/null +++ b/src/components/MarkTypeStrategy/Signature/Render.tsx @@ -0,0 +1,27 @@ +import { useEffect, useState } from 'react' +import SignaturePad from 'signature_pad' +import { SIGNATURE_PAD_OPTIONS, SIGNATURE_PAD_SIZE } from '../../../utils' +import { BasicPoint } from 'signature_pad/dist/types/point' +import { MarkRenderProps } from '../MarkStrategy' +import styles from './Render.module.scss' + +export const MarkRenderSignature = ({ value }: MarkRenderProps) => { + const [dataUrl, setDataUrl] = useState() + + useEffect(() => { + if (value) { + const canvas = document.createElement('canvas') + canvas.width = SIGNATURE_PAD_SIZE.width + canvas.height = SIGNATURE_PAD_SIZE.height + const pad = new SignaturePad(canvas, SIGNATURE_PAD_OPTIONS) + pad.fromData( + JSON.parse(value).map((p: BasicPoint[]) => ({ + points: p + })) + ) + setDataUrl(canvas.toDataURL('image/webp')) + } + }, [value]) + + return dataUrl ? : null +} diff --git a/src/components/MarkTypeStrategy/Signature/index.tsx b/src/components/MarkTypeStrategy/Signature/index.tsx new file mode 100644 index 0000000..aa3429d --- /dev/null +++ b/src/components/MarkTypeStrategy/Signature/index.tsx @@ -0,0 +1,89 @@ +import axios from 'axios' +import { + decryptArrayBuffer, + encryptArrayBuffer, + getHash, + uploadToFileStorage +} from '../../../utils' +import { MarkStrategy } from '../MarkStrategy' +import { MarkInputSignature } from './Input' +import { MarkRenderSignature } from './Render' + +export const SignatureStrategy: MarkStrategy = { + input: MarkInputSignature, + render: MarkRenderSignature, + encryptAndUpload: async (value, encryptionKey) => { + // Value is the stringified signature object + // Encode it to the arrayBuffer + const encoder = new TextEncoder() + const uint8Array = encoder.encode(value) + + if (!encryptionKey) { + throw new Error('Signature requires an encryption key') + } + + // Encrypt the file contents with the same encryption key from the create signature + const encryptedArrayBuffer = await encryptArrayBuffer( + uint8Array, + encryptionKey + ) + + const hash = await getHash(encryptedArrayBuffer) + if (!hash) { + throw new Error("Can't get encrypted file hash.") + } + + // Create the encrypted json file from array buffer and hash + const file = new File([encryptedArrayBuffer], `${hash}.json`) + + try { + const url = await uploadToFileStorage(file) + console.info(`${file.name} uploaded to file storage`) + return url + } catch (error) { + if (error instanceof Error) { + console.error( + `Error occurred in uploading file ${file.name}`, + error.message + ) + } + } + + return value + }, + fetchAndDecrypt: async (value, encryptionKey) => { + if (!encryptionKey) { + throw new Error('Signature requires an encryption key') + } + + const encryptedArrayBuffer = await axios.get(value, { + responseType: 'arraybuffer' + }) + + // Verify hash + const parts = value.split('/') + const urlHash = parts[parts.length - 1] + const hash = await getHash(encryptedArrayBuffer.data) + if (hash !== urlHash) { + // TODO: handle hash verification failing + throw new Error('Unable to verify signature') + } + + const arrayBuffer = await decryptArrayBuffer( + encryptedArrayBuffer.data, + encryptionKey + ).catch((err) => { + console.log('err in decryption:>> ', err) + return null + }) + + if (arrayBuffer) { + // decode json + const decoder = new TextDecoder() + const json = decoder.decode(arrayBuffer) + return json + } + + return value + } +} diff --git a/src/components/MarkTypeStrategy/Text/Input.tsx b/src/components/MarkTypeStrategy/Text/Input.tsx new file mode 100644 index 0000000..6ecd9fc --- /dev/null +++ b/src/components/MarkTypeStrategy/Text/Input.tsx @@ -0,0 +1,19 @@ +import { MarkInputProps } from '../MarkStrategy' +import styles from '../../MarkFormField/style.module.scss' + +export const MarkInputText = ({ + value, + handler, + placeholder +}: MarkInputProps) => { + return ( + { + handler(e.currentTarget.value) + }} + value={value} + /> + ) +} diff --git a/src/components/MarkTypeStrategy/Text/index.tsx b/src/components/MarkTypeStrategy/Text/index.tsx new file mode 100644 index 0000000..b5c3568 --- /dev/null +++ b/src/components/MarkTypeStrategy/Text/index.tsx @@ -0,0 +1,7 @@ +import { MarkStrategy } from '../MarkStrategy' +import { MarkInputText } from './Input' + +export const TextStrategy: MarkStrategy = { + input: MarkInputText, + render: ({ value }) => <>{value} +} diff --git a/src/components/PDFView/PdfMarkItem.tsx b/src/components/PDFView/PdfMarkItem.tsx index cb06455..a1dddb3 100644 --- a/src/components/PDFView/PdfMarkItem.tsx +++ b/src/components/PDFView/PdfMarkItem.tsx @@ -4,6 +4,7 @@ import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' import { useScale } from '../../hooks/useScale.tsx' import { forwardRef } from 'react' import { npubToHex } from '../../utils/nostr.ts' +import { MarkRender } from '../MarkTypeStrategy/MarkRender.tsx' interface PdfMarkItemProps { userMark: CurrentUserMark @@ -31,7 +32,7 @@ const PdfMarkItem = forwardRef(
( fontSize: inPx(from(pageWidth, FONT_SIZE)) }} > - {getMarkValue()} +
) } diff --git a/src/components/PDFView/PdfMarking.tsx b/src/components/PDFView/PdfMarking.tsx index 61968b0..94e3333 100644 --- a/src/components/PDFView/PdfMarking.tsx +++ b/src/components/PDFView/PdfMarking.tsx @@ -24,11 +24,11 @@ import { interface PdfMarkingProps { currentUserMarks: CurrentUserMark[] files: CurrentUserFile[] - handleDownload: () => void + handleSign: () => void + handleSignOffline: () => void meta: Meta | null otherUserMarks: Mark[] setCurrentUserMarks: (currentUserMarks: CurrentUserMark[]) => void - setIsMarksCompleted: (isMarksCompleted: boolean) => void setUpdatedMarks: (markToUpdate: Mark) => void } @@ -38,17 +38,16 @@ interface PdfMarkingProps { * @param props * @constructor */ -const PdfMarking = (props: PdfMarkingProps) => { - const { - files, - currentUserMarks, - setIsMarksCompleted, - setCurrentUserMarks, - setUpdatedMarks, - handleDownload, - meta, - otherUserMarks - } = props +const PdfMarking = ({ + files, + currentUserMarks, + setCurrentUserMarks, + setUpdatedMarks, + handleSign, + handleSignOffline, + meta, + otherUserMarks +}: PdfMarkingProps) => { const [selectedMark, setSelectedMark] = useState(null) const [selectedMarkValue, setSelectedMarkValue] = useState('') const [currentFile, setCurrentFile] = useState(null) @@ -70,8 +69,8 @@ const PdfMarking = (props: PdfMarkingProps) => { const handleMarkClick = (id: number) => { const nextMark = currentUserMarks.find((mark) => mark.mark.id === id) - setSelectedMark(nextMark!) - setSelectedMarkValue(nextMark?.mark.value ?? EMPTY) + + if (nextMark) handleCurrentUserMarkChange(nextMark) } const handleCurrentUserMarkChange = (mark: CurrentUserMark) => { @@ -86,39 +85,45 @@ const PdfMarking = (props: PdfMarkingProps) => { updatedSelectedMark ) setCurrentUserMarks(updatedCurrentUserMarks) - setSelectedMarkValue(mark.currentValue ?? EMPTY) - setSelectedMark(mark) + + // If clicking on the same mark, don't update the value, otherwise do update + if (mark.id !== selectedMark.id) { + setSelectedMarkValue(mark.currentValue ?? EMPTY) + setSelectedMark(mark) + } } - const handleSubmit = (event: React.FormEvent) => { + /** + * Sign and Complete + */ + const handleSubmit = ( + event: React.MouseEvent, + type: 'online' | 'offline' + ) => { event.preventDefault() - if (!selectedMarkValue || !selectedMark) return + if (selectedMarkValue && selectedMark) { + const updatedMark: CurrentUserMark = getUpdatedMark( + selectedMark, + selectedMarkValue + ) - const updatedMark: CurrentUserMark = getUpdatedMark( - selectedMark, - selectedMarkValue - ) + setSelectedMarkValue(EMPTY) + const updatedCurrentUserMarks = updateCurrentUserMarks( + currentUserMarks, + updatedMark + ) + setCurrentUserMarks(updatedCurrentUserMarks) + setSelectedMark(null) + setUpdatedMarks(updatedMark.mark) + } - setSelectedMarkValue(EMPTY) - const updatedCurrentUserMarks = updateCurrentUserMarks( - currentUserMarks, - updatedMark - ) - setCurrentUserMarks(updatedCurrentUserMarks) - setSelectedMark(null) - setIsMarksCompleted(true) - setUpdatedMarks(updatedMark.mark) + if (type === 'online') handleSign() + else if (type === 'offline') handleSignOffline() } - // const updateCurrentUserMarkValues = () => { - // const updatedMark: CurrentUserMark = getUpdatedMark(selectedMark!, selectedMarkValue) - // const updatedCurrentUserMarks = updateCurrentUserMarks(currentUserMarks, updatedMark) - // setSelectedMarkValue(EMPTY) - // setCurrentUserMarks(updatedCurrentUserMarks) - // } - - const handleChange = (event: React.ChangeEvent) => - setSelectedMarkValue(event.target.value) + const handleChange = (value: string) => { + setSelectedMarkValue(value) + } return ( <> @@ -131,7 +136,6 @@ const PdfMarking = (props: PdfMarkingProps) => { files={files} currentFile={currentFile} setCurrentFile={setCurrentFile} - handleDownload={handleDownload} /> )}
@@ -141,28 +145,24 @@ const PdfMarking = (props: PdfMarkingProps) => { centerIcon={faPen} rightIcon={faCircleInfo} > - {currentUserMarks?.length > 0 && ( - - )} - - {selectedMark !== null && ( - - )} + + ) diff --git a/src/components/PDFView/PdfPageItem.tsx b/src/components/PDFView/PdfPageItem.tsx index 5d4be7d..d4381ff 100644 --- a/src/components/PDFView/PdfPageItem.tsx +++ b/src/components/PDFView/PdfPageItem.tsx @@ -6,6 +6,7 @@ import { useEffect, useRef } from 'react' import pdfViewStyles from './style.module.scss' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' import { useScale } from '../../hooks/useScale.tsx' +import { MarkRender } from '../MarkTypeStrategy/MarkRender.tsx' interface PdfPageProps { fileName: string pageIndex: number @@ -73,7 +74,7 @@ const PdfPageItem = ({ fontSize: inPx(from(page.width, FONT_SIZE)) }} > - {m.value} +
) })} diff --git a/src/components/PDFView/index.tsx b/src/components/PDFView/index.tsx index acd1874..88a8983 100644 --- a/src/components/PDFView/index.tsx +++ b/src/components/PDFView/index.tsx @@ -38,25 +38,28 @@ const PdfView = ({ currentUserMarks: CurrentUserMark[], hash: string ): CurrentUserMark[] => { - return currentUserMarks.filter( - (currentUserMark) => currentUserMark.mark.pdfFileHash === hash + return currentUserMarks.filter((currentUserMark) => + currentUserMark.mark.pdfFileHash + ? currentUserMark.mark.pdfFileHash === hash + : currentUserMark.mark.fileHash === hash ) } const filterMarksByFile = (marks: Mark[], hash: string): Mark[] => { - return marks.filter((mark) => mark.pdfFileHash === hash) + return marks.filter((mark) => + mark.pdfFileHash ? mark.pdfFileHash === hash : mark.fileHash === hash + ) } - const isNotLastPdfFile = (index: number, files: CurrentUserFile[]): boolean => - index !== files.length - 1 return (
{files.length > 0 ? ( - files.map((currentUserFile, index, arr) => { - const { hash, file, id } = currentUserFile + files + .map((currentUserFile) => { + const { hash, file, id } = currentUserFile - if (!hash) return - return ( - + if (!hash) return + return (
(pdfRefs.current[id] = el)} @@ -70,10 +73,13 @@ const PdfView = ({ otherUserMarks={filterMarksByFile(otherUserMarks, hash)} />
- {isNotLastPdfFile(index, arr) && } -
- ) - }) + ) + }) + .reduce((prev, curr, i) => [ + prev, + , + curr + ]) ) : ( )} diff --git a/src/components/UserAvatar/index.tsx b/src/components/UserAvatar/index.tsx index 4c49e33..61617a4 100644 --- a/src/components/UserAvatar/index.tsx +++ b/src/components/UserAvatar/index.tsx @@ -23,7 +23,7 @@ export const UserAvatar = ({ }: UserAvatarProps) => { const profile = useProfileMetadata(pubkey) const name = getProfileUsername(pubkey, profile) - const image = profile?.picture + const image = profile?.image return ( { completedAt, parsedSignatureEvents, signedStatus, - isValid + isValid, + id, + timestamps } = useSigitMeta(meta) const { usersPubkey } = useAppSelector((state) => state.auth) const userCanSign = @@ -51,6 +56,50 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => { const { extensions, isSame } = extractFileExtensions(Object.keys(fileHashes)) + const isTimestampVerified = ( + timestamps: OpenTimestamp[], + nostrId: string + ): boolean => { + const matched = timestamps.find((t) => t.nostrId === nostrId) + return !!(matched && matched.verification) + } + + const getOpenTimestampsInfo = ( + timestamps: OpenTimestamp[], + nostrId: string + ) => { + if (isTimestampVerified(timestamps, nostrId)) { + return + } else { + return + } + } + + const getCompletedOpenTimestampsInfo = (timestamp: OpenTimestamp) => { + if (timestamp.verification) { + return + } else { + return + } + } + + const getTimestampTooltipTitle = (label: string, isVerified: boolean) => { + return `${label} / Open Timestamp ${isVerified ? 'Verified' : 'Pending'}` + } + + const isUserSignatureTimestampVerified = () => { + if ( + userCanSign && + hexToNpub(usersPubkey) in parsedSignatureEvents && + timestamps && + timestamps.length > 0 + ) { + const nostrId = parsedSignatureEvents[hexToNpub(usersPubkey)].id + return isTimestampVerified(timestamps, nostrId) + } + return false + } + return submittedBy ? (
@@ -115,19 +164,35 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => {

Details

{' '} - {createdAt ? formatTimestamp(createdAt) : <>—} + {createdAt ? formatTimestamp(createdAt) : <>—}{' '} + {timestamps && + timestamps.length > 0 && + id && + getOpenTimestampsInfo(timestamps, id)} 0 && + timestamps[timestamps.length - 1].verification + ) + )} placement="top" arrow disableInteractive @@ -135,13 +200,26 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => { {' '} {completedAt ? formatTimestamp(completedAt) : <>—} + {signedStatus === SigitStatus.Complete && + completedAt && + timestamps && + timestamps.length > 0 && ( + + {getCompletedOpenTimestampsInfo( + timestamps[timestamps.length - 1] + )} + + )} {/* User signed date */} {userCanSign ? ( { ) : ( <>— )} + {hexToNpub(usersPubkey) in parsedSignatureEvents && + timestamps && + timestamps.length > 0 && ( + + {getOpenTimestampsInfo( + timestamps, + parsedSignatureEvents[hexToNpub(usersPubkey)].id + )} + + )} ) : null} diff --git a/src/components/UsersDetails.tsx/style.module.scss b/src/components/UsersDetails.tsx/style.module.scss index 9d906c1..af18b04 100644 --- a/src/components/UsersDetails.tsx/style.module.scss +++ b/src/components/UsersDetails.tsx/style.module.scss @@ -31,8 +31,6 @@ padding: 5px; display: flex; - align-items: center; - justify-content: start; > :first-child { padding: 5px; @@ -44,3 +42,7 @@ color: white; } } + +.ticket { + margin-left: auto; +} diff --git a/src/contexts/NDKContext.tsx b/src/contexts/NDKContext.tsx new file mode 100644 index 0000000..ba1d734 --- /dev/null +++ b/src/contexts/NDKContext.tsx @@ -0,0 +1,299 @@ +import NDK, { + getRelayListForUser, + Hexpubkey, + NDKEvent, + NDKFilter, + NDKRelayList, + NDKRelaySet, + NDKSubscriptionCacheUsage, + NDKSubscriptionOptions, + NDKUser, + NDKUserProfile +} from '@nostr-dev-kit/ndk' + +import NDKCacheAdapterDexie from '@nostr-dev-kit/ndk-cache-dexie' + +import { Dexie } from 'dexie' +import { createContext, ReactNode, useEffect, useMemo } from 'react' +import { toast } from 'react-toastify' +import { UserRelaysType } from '../types' +import { + DEFAULT_LOOK_UP_RELAY_LIST, + hexToNpub, + orderEventsChronologically, + SIGIT_RELAY, + timeout +} from '../utils' + +export interface NDKContextType { + ndk: NDK + fetchEvents: ( + filter: NDKFilter, + opts?: NDKSubscriptionOptions + ) => Promise + fetchEvent: ( + filter: NDKFilter, + opts?: NDKSubscriptionOptions + ) => Promise + fetchEventsFromUserRelays: ( + filter: NDKFilter | NDKFilter[], + hexKey: string, + userRelaysType: UserRelaysType, + opts?: NDKSubscriptionOptions + ) => Promise + fetchEventFromUserRelays: ( + filter: NDKFilter | NDKFilter[], + hexKey: string, + userRelaysType: UserRelaysType, + opts?: NDKSubscriptionOptions + ) => Promise + findMetadata: ( + pubkey: string, + opts?: NDKSubscriptionOptions + ) => Promise + getNDKRelayList: (pubkey: Hexpubkey) => Promise + publish: (event: NDKEvent, explicitRelayUrls?: string[]) => Promise +} + +// Create the context with an initial value of `null` +export const NDKContext = createContext(null) + +// Create a provider component to wrap around parts of your app +export const NDKContextProvider = ({ children }: { children: ReactNode }) => { + useEffect(() => { + window.onunhandledrejection = async (event: PromiseRejectionEvent) => { + event.preventDefault() + if (event.reason?.name === Dexie.errnames.DatabaseClosed) { + console.log( + 'Could not open Dexie DB, probably version change. Deleting old DB and reloading...' + ) + await Dexie.delete('degmod-db') + // Must reload to open a brand new DB + window.location.reload() + } + } + }, []) + + const ndk = useMemo(() => { + if (import.meta.env.MODE === 'development') { + localStorage.setItem('debug', '*') + } + const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'sigit-db' }) + dexieAdapter.locking = true + const ndk = new NDK({ + enableOutboxModel: true, + autoConnectUserRelays: true, + autoFetchUserMutelist: true, + explicitRelayUrls: [...DEFAULT_LOOK_UP_RELAY_LIST], + cacheAdapter: dexieAdapter + }) + ndk.connect() + + return ndk + }, []) + + /** + * Asynchronously retrieves multiple event based on a provided filter. + * + * @param filter - The filter criteria to find the event. + * @returns Returns a promise that resolves to the found event or null if not found. + */ + const fetchEvents = async ( + filter: NDKFilter, + opts?: NDKSubscriptionOptions + ): Promise => { + return ndk + .fetchEvents(filter, { + closeOnEose: true, + cacheUsage: NDKSubscriptionCacheUsage.PARALLEL, + ...opts + }) + .then((ndkEventSet) => { + const ndkEvents = Array.from(ndkEventSet) + return orderEventsChronologically(ndkEvents) + }) + .catch((err) => { + // Log the error and show a notification if fetching fails + console.error('An error occurred in fetching events', err) + toast.error('An error occurred in fetching events') // Show error notification + return [] // Return an empty array in case of an error + }) + } + + /** + * Asynchronously retrieves an event based on a provided filter. + * + * @param filter - The filter criteria to find the event. + * @returns Returns a promise that resolves to the found event or null if not found. + */ + const fetchEvent = async ( + filter: NDKFilter, + opts?: NDKSubscriptionOptions + ) => { + const events = await fetchEvents(filter, opts) + if (events.length === 0) return null + return events[0] + } + + /** + * Asynchronously retrieves multiple events from the user's relays based on a specified filter. + * The function first retrieves the user's relays, and then fetches the events using the provided filter. + * + * @param filter - The event filter to use when fetching the event (e.g., kinds, authors). + * @param hexKey - The hexadecimal representation of the user's public key. + * @param userRelaysType - The type of relays to search (e.g., write, read). + * @returns A promise that resolves with an array of events. + */ + const fetchEventsFromUserRelays = async ( + filter: NDKFilter | NDKFilter[], + hexKey: string, + userRelaysType: UserRelaysType, + opts?: NDKSubscriptionOptions + ): Promise => { + // Find the user's relays (10s timeout). + const relayUrls = await Promise.race([ + getRelayListForUser(hexKey, ndk), + timeout(3000) + ]) + .then((ndkRelayList) => { + if (ndkRelayList) return ndkRelayList[userRelaysType] + return [] // Return an empty array if ndkRelayList is undefined + }) + .catch((err) => { + console.error( + `An error occurred in fetching user's (${hexKey}) ${userRelaysType}`, + err + ) + return [] as string[] + }) + + if (!relayUrls.includes(SIGIT_RELAY)) { + relayUrls.push(SIGIT_RELAY) + } + + return ndk + .fetchEvents( + filter, + { + closeOnEose: true, + cacheUsage: NDKSubscriptionCacheUsage.PARALLEL, + ...opts + }, + relayUrls.length + ? NDKRelaySet.fromRelayUrls(relayUrls, ndk, true) + : undefined + ) + .then((ndkEventSet) => { + const ndkEvents = Array.from(ndkEventSet) + return orderEventsChronologically(ndkEvents) + }) + .catch((err) => { + // Log the error and show a notification if fetching fails + console.error('An error occurred in fetching events', err) + toast.error('An error occurred in fetching events') // Show error notification + return [] // Return an empty array in case of an error + }) + } + + /** + * Fetches an event from the user's relays based on a specified filter. + * The function first retrieves the user's relays, and then fetches the event using the provided filter. + * + * @param filter - The event filter to use when fetching the event (e.g., kinds, authors). + * @param hexKey - The hexadecimal representation of the user's public key. + * @param userRelaysType - The type of relays to search (e.g., write, read). + * @returns A promise that resolves to the fetched event or null if the operation fails. + */ + const fetchEventFromUserRelays = async ( + filter: NDKFilter | NDKFilter[], + hexKey: string, + userRelaysType: UserRelaysType, + opts?: NDKSubscriptionOptions + ) => { + const events = await fetchEventsFromUserRelays( + filter, + hexKey, + userRelaysType, + opts + ) + if (events.length === 0) return null + return events[0] + } + + /** + * Finds metadata for a given pubkey. + * + * @param hexKey - The pubkey to search for metadata. + * @returns A promise that resolves to the metadata event. + */ + const findMetadata = async ( + pubkey: string, + opts?: NDKSubscriptionOptions + ): Promise => { + const npub = hexToNpub(pubkey) + + const user = new NDKUser({ npub }) + user.ndk = ndk + + return await user.fetchProfile({ + cacheUsage: NDKSubscriptionCacheUsage.PARALLEL, + ...(opts || {}) + }) + } + + const getNDKRelayList = async (pubkey: Hexpubkey) => { + const ndkRelayList = await Promise.race([ + getRelayListForUser(pubkey, ndk), + timeout(10000) + ]).catch(() => { + const relayList = new NDKRelayList(ndk) + relayList.bothRelayUrls = [SIGIT_RELAY] + return relayList + }) + + return ndkRelayList + } + + const publish = async ( + event: NDKEvent, + explicitRelayUrls?: string[] + ): Promise => { + if (!event.sig) throw new Error('Before publishing first sign the event!') + + let ndkRelaySet: NDKRelaySet | undefined + + if (explicitRelayUrls && explicitRelayUrls.length > 0) { + if (!explicitRelayUrls.includes(SIGIT_RELAY)) { + explicitRelayUrls = [...explicitRelayUrls, SIGIT_RELAY] + } + ndkRelaySet = NDKRelaySet.fromRelayUrls(explicitRelayUrls, ndk) + } + + return await Promise.race([event.publish(ndkRelaySet), timeout(3000)]) + .then((res) => { + const relaysPublishedOn = Array.from(res) + return relaysPublishedOn.map((relay) => relay.url) + }) + .catch((err) => { + console.error(`An error occurred in publishing event`, err) + return [] + }) + } + + return ( + + {children} + + ) +} diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts deleted file mode 100644 index 6536e19..0000000 --- a/src/controllers/AuthController.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { EventTemplate } from 'nostr-tools' -import { MetadataController, NostrController } from '.' -import { appPrivateRoutes } from '../routes' -import { - setAuthState, - setMetadataEvent, - setRelayMapAction -} from '../store/actions' -import store from '../store/store' -import { SignedEvent } from '../types' -import { - base64DecodeAuthToken, - base64EncodeSignedEvent, - compareObjects, - getAuthToken, - getRelayMap, - getVisitedLink, - saveAuthToken, - unixNow -} from '../utils' - -export class AuthController { - private nostrController: NostrController - private metadataController: MetadataController - - constructor() { - this.nostrController = NostrController.getInstance() - this.metadataController = MetadataController.getInstance() - } - - /** - * Function will authenticate user by signing an auth event - * which is done by calling the sign() function, where appropriate - * method will be chosen (extension or keys) - * - * @param pubkey of the user trying to login - * @returns url to redirect if authentication successfull - * or error if otherwise - */ - async authAndGetMetadataAndRelaysMap(pubkey: string) { - const emptyMetadata = this.metadataController.getEmptyMetadataEvent() - - this.metadataController - .findMetadata(pubkey) - .then((event) => { - if (event) { - store.dispatch(setMetadataEvent(event)) - } else { - store.dispatch(setMetadataEvent(emptyMetadata)) - } - }) - .catch((err) => { - console.warn('Error occurred while finding metadata', err) - - store.dispatch(setMetadataEvent(emptyMetadata)) - }) - - // Nostr uses unix timestamps - const timestamp = unixNow() - const { href } = window.location - - const authEvent: EventTemplate = { - kind: 27235, - tags: [ - ['u', href], - ['method', 'GET'] - ], - content: '', - created_at: timestamp - } - - const signedAuthEvent = await this.nostrController.signEvent(authEvent) - this.createAndSaveAuthToken(signedAuthEvent) - - store.dispatch( - setAuthState({ - loggedIn: true, - usersPubkey: pubkey - }) - ) - - const relayMap = await getRelayMap(pubkey) - - if (Object.keys(relayMap).length < 1) { - // Navigate user to relays page if relay map is empty - return Promise.resolve(appPrivateRoutes.relays) - } - - if (store.getState().auth.loggedIn) { - if (!compareObjects(store.getState().relays?.map, relayMap.map)) - store.dispatch(setRelayMapAction(relayMap.map)) - } - - const currentLocation = window.location.hash.replace('#', '') - - if (!Object.values(appPrivateRoutes).includes(currentLocation)) { - // User did change the location to one of the private routes - const visitedLink = getVisitedLink() - - if (visitedLink) { - const { pathname, search } = visitedLink - - return Promise.resolve(`${pathname}${search}`) - } else { - // Navigate user in - return Promise.resolve(appPrivateRoutes.homePage) - } - } - } - - checkSession() { - const savedAuthToken = getAuthToken() - - if (savedAuthToken) { - const signedEvent = base64DecodeAuthToken(savedAuthToken) - - store.dispatch( - setAuthState({ - loggedIn: true, - usersPubkey: signedEvent.pubkey - }) - ) - - return - } - - store.dispatch( - setAuthState({ - loggedIn: false, - usersPubkey: undefined - }) - ) - } - - private createAndSaveAuthToken(signedAuthEvent: SignedEvent) { - const base64Encoded = base64EncodeSignedEvent(signedAuthEvent) - - // save newly created auth token (base64 nostr singed event) in local storage along with expiry time - saveAuthToken(base64Encoded) - return base64Encoded - } -} diff --git a/src/controllers/MetadataController.ts b/src/controllers/MetadataController.ts deleted file mode 100644 index 984afd3..0000000 --- a/src/controllers/MetadataController.ts +++ /dev/null @@ -1,219 +0,0 @@ -import { - Event, - Filter, - VerifiedEvent, - kinds, - validateEvent, - verifyEvent -} from 'nostr-tools' -import { toast } from 'react-toastify' -import { EventEmitter } from 'tseep' -import { NostrController, relayController } from '.' -import { localCache } from '../services' -import { ProfileMetadata, RelaySet } from '../types' -import { - findRelayListAndUpdateCache, - findRelayListInCache, - getDefaultRelaySet, - getUserRelaySet, - isOlderThanOneDay, - unixNow -} from '../utils' -import { DEFAULT_LOOK_UP_RELAY_LIST } from '../utils/const' - -export class MetadataController extends EventEmitter { - private static instance: MetadataController - private nostrController: NostrController - private specialMetadataRelay = 'wss://purplepag.es' - private pendingFetches = new Map>() // Track pending fetches - - constructor() { - super() - this.nostrController = NostrController.getInstance() - } - - public static getInstance(): MetadataController { - if (!MetadataController.instance) { - MetadataController.instance = new MetadataController() - } - return MetadataController.instance - } - - /** - * Asynchronously checks for more recent metadata events authored by a specific key. - * If a more recent metadata event is found, it is handled and returned. - * If no more recent event is found, the current event is returned. - * @param hexKey The hexadecimal key of the author to filter metadata events. - * @param currentEvent The current metadata event, if any, to compare with newer events. - * @returns A promise resolving to the most recent metadata event found, or null if none is found. - */ - private async checkForMoreRecentMetadata( - hexKey: string, - currentEvent: Event | null - ): Promise { - // Return the ongoing fetch promise if one exists for the same hexKey - if (this.pendingFetches.has(hexKey)) { - return this.pendingFetches.get(hexKey)! - } - - // Define the event filter to only include metadata events authored by the given key - const eventFilter: Filter = { - kinds: [kinds.Metadata], - authors: [hexKey] - } - - const fetchPromise = relayController - .fetchEvent(eventFilter, DEFAULT_LOOK_UP_RELAY_LIST) - .catch((err) => { - console.error(err) - return null - }) - .finally(() => { - this.pendingFetches.delete(hexKey) - }) - - this.pendingFetches.set(hexKey, fetchPromise) - - const metadataEvent = await fetchPromise - - if ( - metadataEvent && - validateEvent(metadataEvent) && - verifyEvent(metadataEvent) - ) { - if ( - !currentEvent || - metadataEvent.created_at >= currentEvent.created_at - ) { - this.handleNewMetadataEvent(metadataEvent) - } - return metadataEvent - } - - // todo/implement: if no valid metadata event is found in DEFAULT_LOOK_UP_RELAY_LIST - // try to query user relay list - - // if current event is null we should cache empty metadata event for provided hexKey - if (!currentEvent) { - const emptyMetadata = this.getEmptyMetadataEvent(hexKey) - this.handleNewMetadataEvent(emptyMetadata as VerifiedEvent) - } - - return currentEvent - } - - /** - * Handle new metadata events and emit them to subscribers - */ - private async handleNewMetadataEvent(event: VerifiedEvent) { - // update the event in local cache - localCache.addUserMetadata(event) - // Emit the event to subscribers. - this.emit(event.pubkey, event.kind, event) - } - - /** - * Finds metadata for a given hexadecimal key. - * - * @param hexKey - The hexadecimal key to search for metadata. - * @returns A promise that resolves to the metadata event. - */ - public findMetadata = async (hexKey: string): Promise => { - // Attempt to retrieve the metadata event from the local cache - const cachedMetadataEvent = await localCache.getUserMetadata(hexKey) - - // If cached metadata is found, check its validity - if (cachedMetadataEvent) { - // Check if the cached metadata is older than one day - if (isOlderThanOneDay(cachedMetadataEvent.cachedAt)) { - // If older than one week, find the metadata from relays in background - this.checkForMoreRecentMetadata(hexKey, cachedMetadataEvent.event) - } - - // Return the cached metadata event - return cachedMetadataEvent.event - } - - // If no cached metadata is found, retrieve it from relays - return this.checkForMoreRecentMetadata(hexKey, null) - } - - /** - * Based on the hexKey of the current user, this method attempts to retrieve a relay set. - * @func findRelayListInCache first checks if there is already an up-to-date - * relay list available in cache; if not - - * @func findRelayListAndUpdateCache checks if the relevant relay event is available from - * the purple pages relay; - * @func findRelayListAndUpdateCache will run again if the previous two calls return null and - * check if the relevant relay event can be obtained from 'most popular relays' - * If relay event is found, it will be saved in cache for future use - * @param hexKey of the current user - * @return RelaySet which will contain either relays extracted from the user Relay Event - * or a fallback RelaySet with Sigit's Relay - */ - public findRelayListMetadata = async (hexKey: string): Promise => { - const relayEvent = - (await findRelayListInCache(hexKey)) || - (await findRelayListAndUpdateCache(DEFAULT_LOOK_UP_RELAY_LIST, hexKey)) - - return relayEvent ? getUserRelaySet(relayEvent.tags) : getDefaultRelaySet() - } - - public extractProfileMetadataContent = (event: Event) => { - try { - if (!event.content) return {} - return JSON.parse(event.content) as ProfileMetadata - } catch (error) { - console.log('error in parsing metadata event content :>> ', error) - return null - } - } - - /** - * Function will not sign provided event if the SIG exists - */ - public publishMetadataEvent = async (event: Event) => { - let signedMetadataEvent = event - - if (event.sig.length < 1) { - const timestamp = unixNow() - - // Metadata event to publish to the wss://purplepag.es relay - const newMetadataEvent: Event = { - ...event, - created_at: timestamp - } - - signedMetadataEvent = - await this.nostrController.signEvent(newMetadataEvent) - } - - await relayController - .publish(signedMetadataEvent, [this.specialMetadataRelay]) - .then((relays) => { - if (relays.length) { - toast.success(`Metadata event published on: ${relays.join('\n')}`) - this.handleNewMetadataEvent(signedMetadataEvent as VerifiedEvent) - } else { - toast.error('Could not publish metadata event to any relay!') - } - }) - .catch((err) => { - toast.error(err.message) - }) - } - - public validate = (event: Event) => validateEvent(event) && verifyEvent(event) - - public getEmptyMetadataEvent = (pubkey?: string): Event => { - return { - content: '', - created_at: new Date().valueOf(), - id: '', - kind: 0, - pubkey: pubkey || '', - sig: '', - tags: [] - } - } -} diff --git a/src/controllers/NostrController.ts b/src/controllers/NostrController.ts index c3d2908..8e24e91 100644 --- a/src/controllers/NostrController.ts +++ b/src/controllers/NostrController.ts @@ -1,9 +1,12 @@ import { EventTemplate, UnsignedEvent } from 'nostr-tools' -import { WindowNostr } from 'nostr-tools/nip07' import { EventEmitter } from 'tseep' import store from '../store/store' import { SignedEvent } from '../types' import { LoginMethodContext } from '../services/LoginMethodStrategy/loginMethodContext' +import { clear, unixNow } from '../utils' +import { LoginMethod } from '../store/auth/types' +import { logout as nostrLogout } from 'nostr-login' +import { userLogOutAction } from '../store/actions' export class NostrController extends EventEmitter { private static instance: NostrController @@ -11,13 +14,6 @@ export class NostrController extends EventEmitter { private constructor() { super() } - private getNostrObject = () => { - if (window.nostr) return window.nostr as WindowNostr - - throw new Error( - `window.nostr object not present. Make sure you have an nostr extension installed/working properly.` - ) - } public static getInstance(): NostrController { if (!NostrController.instance) { @@ -72,7 +68,22 @@ export class NostrController extends EventEmitter { const loginMethod = store.getState().auth.loginMethod const context = new LoginMethodContext(loginMethod) - return await context.signEvent(event) + const authkey = store.getState().auth.usersPubkey + const signedEvent = await context.signEvent(event) + const pubkey = signedEvent.pubkey + + // Forcefully log out the user if we detect missmatch between pubkeys + // Allow undefined authkey, intial log in + if (authkey && authkey !== pubkey) { + if (loginMethod === LoginMethod.nostrLogin) { + nostrLogout() + } + store.dispatch(userLogOutAction()) + clear() + throw new Error('User missmatch.\n\nPlease log in again.') + } + + return signedEvent } nip04Encrypt = async (receiver: string, content: string): Promise => { @@ -97,23 +108,37 @@ export class NostrController extends EventEmitter { } /** - * Function will capture the public key from the nostr extension or if no extension present - * function wil capture the public key from the local storage + * Function will capture the public key from signedEvent */ capturePublicKey = async (): Promise => { - const nostr = this.getNostrObject() - const pubKey = await nostr.getPublicKey().catch((err: unknown) => { - if (err instanceof Error) { - return Promise.reject(err.message) - } else { - return Promise.reject(JSON.stringify(err)) + try { + const timestamp = unixNow() + const { href } = window.location + + const authEvent: EventTemplate = { + kind: 27235, + tags: [ + ['u', href], + ['method', 'GET'] + ], + content: '', + created_at: timestamp } - }) - if (!pubKey) { - return Promise.reject('Error getting public key, user canceled') + const signedAuthEvent = await this.signEvent(authEvent) + const pubkey = signedAuthEvent.pubkey + + if (!pubkey) { + return Promise.reject('Error getting public key, user canceled') + } + + return Promise.resolve(pubkey) + } catch (error) { + if (error instanceof Error) { + return Promise.reject(error.message) + } else { + return Promise.reject(JSON.stringify(error)) + } } - - return Promise.resolve(pubKey) } } diff --git a/src/controllers/RelayController.ts b/src/controllers/RelayController.ts deleted file mode 100644 index df33b4b..0000000 --- a/src/controllers/RelayController.ts +++ /dev/null @@ -1,306 +0,0 @@ -import { Event, Filter, Relay } from 'nostr-tools' -import { - settleAllFullfilfedPromises, - normalizeWebSocketURL, - timeout -} from '../utils' -import { SIGIT_RELAY } from '../utils/const' - -/** - * Singleton class to manage relay operations. - */ -export class RelayController { - private static instance: RelayController - private pendingConnections = new Map>() // Track pending connections - public connectedRelays = new Map() - - private constructor() {} - - /** - * Provides the singleton instance of RelayController. - * - * @returns The singleton instance of RelayController. - */ - public static getInstance(): RelayController { - if (!RelayController.instance) { - RelayController.instance = new RelayController() - } - return RelayController.instance - } - - /** - * Connects to a relay server if not already connected. - * - * This method checks if a relay with the given URL is already in the list of connected relays. - * If it is not connected, it attempts to establish a new connection. - * On successful connection, the relay is added to the list of connected relays and returned. - * If the connection fails, an error is logged and `null` is returned. - * - * @param relayUrl - The URL of the relay server to connect to. - * @returns A promise that resolves to the connected relay object if successful, or `null` if the connection fails. - */ - public connectRelay = async (relayUrl: string): Promise => { - const normalizedWebSocketURL = normalizeWebSocketURL(relayUrl) - const relay = this.connectedRelays.get(normalizedWebSocketURL) - - if (relay) { - if (relay.connected) return relay - - // If relay is found in connectedRelay map but not connected, - // remove it from map and call connectRelay method again - this.connectedRelays.delete(relayUrl) - return this.connectRelay(relayUrl) - } - - // Check if there's already a pending connection for this relay URL - if (this.pendingConnections.has(relayUrl)) { - // Return the existing promise to avoid making another connection - return this.pendingConnections.get(relayUrl)! - } - - // Create a new connection promise and store it in pendingConnections - const connectionPromise = Relay.connect(relayUrl) - .then((relay) => { - if (relay.connected) { - // Add the newly connected relay to the connected relays map - this.connectedRelays.set(relayUrl, relay) - - // Return the newly connected relay - return relay - } - - return null - }) - .catch((err) => { - // Log an error message if the connection fails - console.error(`Relay connection failed: ${relayUrl}`, err) - - // Return null to indicate connection failure - return null - }) - .finally(() => { - // Remove the connection from pendingConnections once it settles - this.pendingConnections.delete(relayUrl) - }) - - this.pendingConnections.set(relayUrl, connectionPromise) - return connectionPromise - } - - /** - * Asynchronously retrieves multiple event from a set of relays based on a provided filter. - * If no relays are specified, it defaults to using connected relays. - * - * @param filter - The filter criteria to find the event. - * @param relays - An optional array of relay URLs to search for the event. - * @returns Returns a promise that resolves with an array of events. - */ - fetchEvents = async ( - filter: Filter, - relayUrls: string[] = [] - ): Promise => { - if (!relayUrls.includes(SIGIT_RELAY)) { - /** - * NOTE: To avoid side-effects on external relayUrls array passed as argument - * re-assigned relayUrls with added sigit relay instead of just appending to same array - */ - - relayUrls = [...relayUrls, SIGIT_RELAY] // Add app relay to relays array if not exists already - } - - // connect to all specified relays - const relays = await settleAllFullfilfedPromises( - relayUrls, - this.connectRelay - ) - - // Check if any relays are connected - if (relays.length === 0) { - throw new Error('No relay is connected to fetch events!') - } - - const events: Event[] = [] - const eventIds = new Set() // To keep track of event IDs and avoid duplicates - - // Create a promise for each relay subscription - const subPromises = relays.map((relay) => { - return new Promise((resolve) => { - if (!relay.connected) { - console.log(`${relay.url} : Not connected!`, 'Skipping subscription') - return resolve() - } - - // Subscribe to the relay with the specified filter - const sub = relay.subscribe([filter], { - // Handle incoming events - onevent: (e) => { - // Add the event to the array if it's not a duplicate - if (!eventIds.has(e.id)) { - eventIds.add(e.id) // Record the event ID - events.push(e) // Add the event to the array - } - }, - // Handle the End-Of-Stream (EOSE) message - oneose: () => { - sub.close() // Close the subscription - resolve() // Resolve the promise when EOSE is received - } - }) - - // add a 30 sec of timeout to subscription - setTimeout(() => { - if (!sub.closed) { - sub.close() - resolve() - } - }, 30 * 1000) - }) - }) - - // Wait for all subscriptions to complete - await Promise.allSettled(subPromises) - - // It is possible that different relays will send different events and events array may contain more events then specified limit in filter - // To fix this issue we'll first sort these events and then return only limited events - if (filter.limit) { - // Sort events by creation date in descending order - events.sort((a, b) => b.created_at - a.created_at) - - return events.slice(0, filter.limit) - } - - return events - } - - /** - * Asynchronously retrieves an event from a set of relays based on a provided filter. - * If no relays are specified, it defaults to using connected relays. - * - * @param filter - The filter criteria to find the event. - * @param relays - An optional array of relay URLs to search for the event. - * @returns Returns a promise that resolves to the found event or null if not found. - */ - fetchEvent = async ( - filter: Filter, - relays: string[] = [] - ): Promise => { - const events = await this.fetchEvents(filter, relays) - - // Sort events by creation date in descending order - events.sort((a, b) => b.created_at - a.created_at) - - // Return the most recent event, or null if no events were received - return events[0] || null - } - - /** - * Subscribes to events from multiple relays. - * - * This method connects to the specified relay URLs and subscribes to events - * using the provided filter. It handles incoming events through the given - * `eventHandler` callback and manages the subscription lifecycle. - * - * @param filter - The filter criteria to apply when subscribing to events. - * @param relayUrls - An optional array of relay URLs to connect to. The default relay URL (`SIGIT_RELAY`) is added automatically. - * @param eventHandler - A callback function to handle incoming events. It receives an `Event` object. - * - */ - subscribeForEvents = async ( - filter: Filter, - relayUrls: string[] = [], - eventHandler: (event: Event) => void - ) => { - if (!relayUrls.includes(SIGIT_RELAY)) { - /** - * NOTE: To avoid side-effects on external relayUrls array passed as argument - * re-assigned relayUrls with added sigit relay instead of just appending to same array - */ - relayUrls = [...relayUrls, SIGIT_RELAY] // Add app relay to relays array if not exists already - } - - // connect to all specified relays - const relays = await settleAllFullfilfedPromises( - relayUrls, - this.connectRelay - ) - - // Check if any relays are connected - if (relays.length === 0) { - throw new Error('No relay is connected to fetch events!') - } - - const processedEvents: string[] = [] // To keep track of processed events - - // Create a promise for each relay subscription - const subPromises = relays.map((relay) => { - return new Promise((resolve) => { - // Subscribe to the relay with the specified filter - const sub = relay.subscribe([filter], { - // Handle incoming events - onevent: (e) => { - // Process event only if it hasn't been processed before - if (!processedEvents.includes(e.id)) { - processedEvents.push(e.id) - eventHandler(e) // Call the event handler with the event - } - }, - // Handle the End-Of-Stream (EOSE) message - oneose: () => { - sub.close() // Close the subscription - resolve() // Resolve the promise when EOSE is received - } - }) - }) - }) - - // Wait for all subscriptions to complete - await Promise.allSettled(subPromises) - } - - publish = async ( - event: Event, - relayUrls: string[] = [] - ): Promise => { - if (!relayUrls.includes(SIGIT_RELAY)) { - /** - * NOTE: To avoid side-effects on external relayUrls array passed as argument - * re-assigned relayUrls with added sigit relay instead of just appending to same array - */ - relayUrls = [...relayUrls, SIGIT_RELAY] // Add app relay to relays array if not exists already - } - - // connect to all specified relays - const relays = await settleAllFullfilfedPromises( - relayUrls, - this.connectRelay - ) - - // Check if any relays are connected - if (relays.length === 0) { - throw new Error('No relay is connected to publish event!') - } - - const publishedOnRelays: string[] = [] // List to track which relays successfully published the event - - // Create a promise for publishing the event to each connected relay - const publishPromises = relays.map(async (relay) => { - try { - await Promise.race([ - relay.publish(event), // Publish the event to the relay - timeout(20 * 1000) // Set a timeout to handle cases where publishing takes too long - ]) - publishedOnRelays.push(relay.url) // Add the relay URL to the list of successfully published relays - } catch (err) { - console.error(`Failed to publish event on relay: ${relay.url}`, err) - } - }) - - // Wait for all publish operations to complete (either fulfilled or rejected) - await Promise.allSettled(publishPromises) - - // Return the list of relay URLs where the event was published - return publishedOnRelays - } -} - -export const relayController = RelayController.getInstance() diff --git a/src/controllers/index.ts b/src/controllers/index.ts index dc1f76f..e7302ce 100644 --- a/src/controllers/index.ts +++ b/src/controllers/index.ts @@ -1,4 +1 @@ -export * from './AuthController' -export * from './MetadataController' export * from './NostrController' -export * from './RelayController' diff --git a/src/data/metaSamples.json b/src/data/metaSamples.json index 66f6536..69f595e 100644 --- a/src/data/metaSamples.json +++ b/src/data/metaSamples.json @@ -19,7 +19,7 @@ "page": 1 }, "npub": "npub1x77qywdllzetv9ncnhlfpv62kshlgtt0uqlsq3v22uzzkk2xvvrsn6uyfy", - "pdfFileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05" + "fileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05" } ], "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05/2.png": [ @@ -34,7 +34,7 @@ "page": 2 }, "npub": "npub1x77qywdllzetv9ncnhlfpv62kshlgtt0uqlsq3v22uzzkk2xvvrsn6uyfy", - "pdfFileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05" + "fileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05" } ] } @@ -54,7 +54,7 @@ "page": 1 }, "npub": "npub1x77qywdllzetv9ncnhlfpv62kshlgtt0uqlsq3v22uzzkk2xvvrsn6uyfy", - "pdfFileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05", + "fileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05", "value": "Pera Peric" }, { @@ -68,7 +68,7 @@ "page": 2 }, "npub": "npub1x77qywdllzetv9ncnhlfpv62kshlgtt0uqlsq3v22uzzkk2xvvrsn6uyfy", - "pdfFileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05", + "fileHash": "da5f857e77d3aa59c461efad804116931c059b36e6b4da0b5d9452753ec70c05", "value": "Pera Peric" } ] diff --git a/src/hooks/index.ts b/src/hooks/index.ts index e7ec305..cbadfee 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,2 +1,7 @@ export * from './store' +export * from './useAuth' export * from './useDidMount' +export * from './useDvm' +export * from './useLogout' +export * from './useNDK' +export * from './useNDKContext' diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts new file mode 100644 index 0000000..e0e75fb --- /dev/null +++ b/src/hooks/useAuth.ts @@ -0,0 +1,127 @@ +import { EventTemplate } from 'nostr-tools' +import { useCallback } from 'react' +import { NostrController } from '../controllers' +import { appPrivateRoutes } from '../routes' +import { + setAuthState, + setRelayMapAction, + setUserProfile +} from '../store/actions' +import { + base64DecodeAuthToken, + compareObjects, + createAndSaveAuthToken, + getAuthToken, + getRelayMapFromNDKRelayList, + unixNow +} from '../utils' +import { useAppDispatch, useAppSelector } from './store' +import { useNDKContext } from './useNDKContext' +import { useDvm } from './useDvm' + +export const useAuth = () => { + const dispatch = useAppDispatch() + const { getRelayInfo } = useDvm() + const { findMetadata, getNDKRelayList } = useNDKContext() + + const authState = useAppSelector((state) => state.auth) + const relaysState = useAppSelector((state) => state.relays) + + const checkSession = useCallback(() => { + const savedAuthToken = getAuthToken() + + if (savedAuthToken) { + const signedEvent = base64DecodeAuthToken(savedAuthToken) + + dispatch( + setAuthState({ + loggedIn: true, + usersPubkey: signedEvent.pubkey + }) + ) + return + } + + dispatch( + setAuthState({ + loggedIn: false, + usersPubkey: undefined + }) + ) + }, [dispatch]) + + /** + * Function will authenticate user by signing an auth event + * which is done by calling the sign() function, where appropriate + * method will be chosen (extension or keys) + * + * @param pubkey of the user trying to login + * @returns url to redirect if authentication successfull + * or error if otherwise + */ + const authAndGetMetadataAndRelaysMap = useCallback( + async (pubkey: string) => { + try { + const profile = await findMetadata(pubkey) + dispatch(setUserProfile(profile)) + } catch (err) { + console.warn('Error occurred while finding metadata', err) + } + + const timestamp = unixNow() + const { href } = window.location + + const authEvent: EventTemplate = { + kind: 27235, + tags: [ + ['u', href], + ['method', 'GET'] + ], + content: '', + created_at: timestamp + } + + const nostrController = NostrController.getInstance() + const signedAuthEvent = await nostrController.signEvent(authEvent) + createAndSaveAuthToken(signedAuthEvent) + + dispatch( + setAuthState({ + loggedIn: true, + usersPubkey: pubkey + }) + ) + + const ndkRelayList = await getNDKRelayList(pubkey) + const relays = ndkRelayList.relays + + if (relays.length < 1) { + // Navigate user to relays page if relay map is empty + return appPrivateRoutes.relays + } + + getRelayInfo(relays) + + const relayMap = getRelayMapFromNDKRelayList(ndkRelayList) + + if (authState.loggedIn && !compareObjects(relaysState?.map, relayMap)) { + dispatch(setRelayMapAction(relayMap)) + } + + return appPrivateRoutes.homePage + }, + [ + dispatch, + findMetadata, + getNDKRelayList, + getRelayInfo, + authState, + relaysState + ] + ) + + return { + authAndGetMetadataAndRelaysMap, + checkSession + } +} diff --git a/src/hooks/useDvm.ts b/src/hooks/useDvm.ts new file mode 100644 index 0000000..089d16d --- /dev/null +++ b/src/hooks/useDvm.ts @@ -0,0 +1,98 @@ +import { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk' +import { EventTemplate } from 'nostr-tools' +import { NostrController } from '../controllers' +import { setRelayInfoAction } from '../store/actions' +import { RelayInfoObject } from '../types' +import { compareObjects, unixNow } from '../utils' +import { useAppDispatch, useAppSelector } from './store' +import { useNDKContext } from './useNDKContext' + +export const useDvm = () => { + const dvmRelays = [ + 'wss://relay.damus.io', + 'wss://relay.primal.net', + 'wss://relayable.org' + ] + + const relayInfo = useAppSelector((state) => state.relays.info) + + const { ndk, publish } = useNDKContext() + const dispatch = useAppDispatch() + + /** + * Sets information about relays into relays.info app state. + * @param relayURIs - relay URIs to get information about + */ + const getRelayInfo = async (relayURIs: string[]) => { + // initialize job request + const jobEventTemplate: EventTemplate = { + content: '', + created_at: unixNow(), + kind: 68001, + tags: [ + ['i', `${JSON.stringify(relayURIs)}`], + ['j', 'relay-info'] + ] + } + + const nostrController = NostrController.getInstance() + + // sign job request event + const jobSignedEvent = await nostrController.signEvent(jobEventTemplate) + + // publish job request + const ndkEvent = new NDKEvent(ndk, jobSignedEvent) + await publish(ndkEvent, dvmRelays) + + const subscribeWithTimeout = ( + subscription: NDKSubscription, + timeoutMs: number + ): Promise => { + return new Promise((resolve, reject) => { + const eventHandler = (event: NDKEvent) => { + subscription.stop() + resolve(event.content) + } + + subscription.on('event', eventHandler) + + // Set up a timeout to stop the subscription after a specified time + const timeout = setTimeout(() => { + subscription.stop() // Stop the subscription + reject(new Error('Subscription timed out')) // Reject the promise with a timeout error + }, timeoutMs) + + // Handle subscription close event + subscription.on('close', () => clearTimeout(timeout)) + }) + } + + // filter for getting DVM job's result + const sub = ndk.subscribe({ + kinds: [68002 as number], + '#e': [jobSignedEvent.id], + '#p': [jobSignedEvent.pubkey] + }) + + // asynchronously get relay info from dvm job with 20 seconds timeout + const dvmJobResult = await subscribeWithTimeout(sub, 20000) + + if (!dvmJobResult) { + return Promise.reject(`Relay(s) information wasn't received`) + } + + let newRelaysInfo: RelayInfoObject + + try { + newRelaysInfo = JSON.parse(dvmJobResult) + } catch (error) { + return Promise.reject(`Invalid relay(s) information.`) + } + + if (newRelaysInfo && !compareObjects(relayInfo, newRelaysInfo)) { + dispatch(setRelayInfoAction(newRelaysInfo)) + } + } + + return { getRelayInfo } +} diff --git a/src/hooks/useNDK.ts b/src/hooks/useNDK.ts new file mode 100644 index 0000000..ad9e54f --- /dev/null +++ b/src/hooks/useNDK.ts @@ -0,0 +1,512 @@ +import { useCallback } from 'react' +import { toast } from 'react-toastify' + +import { bytesToHex } from '@noble/hashes/utils' +import { + NDKEvent, + NDKFilter, + NDKKind, + NDKRelaySet, + NDKSubscriptionCacheUsage +} from '@nostr-dev-kit/ndk' +import _ from 'lodash' +import { + Event, + generateSecretKey, + getPublicKey, + kinds, + UnsignedEvent +} from 'nostr-tools' + +import { useAppDispatch, useAppSelector, useNDKContext } from '.' +import { NostrController } from '../controllers' +import { + updateProcessedGiftWraps, + updateUserAppData as updateUserAppDataAction +} from '../store/actions' +import { Keys } from '../store/auth/types' +import { + isSigitNotification, + Meta, + SigitNotification, + UserAppData, + UserRelaysType +} from '../types' +import { + countLeadingZeroes, + createWrap, + deleteBlossomFile, + fetchMetaFromFileStorage, + getDTagForUserAppData, + getUserAppDataFromBlossom, + hexToNpub, + parseJson, + SIGIT_RELAY, + unixNow, + uploadUserAppDataToBlossom +} from '../utils' + +export const useNDK = () => { + const dispatch = useAppDispatch() + const { + ndk, + fetchEvent, + fetchEventsFromUserRelays, + publish, + getNDKRelayList + } = useNDKContext() + const usersPubkey = useAppSelector((state) => state.auth.usersPubkey) + const appData = useAppSelector((state) => state.userAppData) + const processedEvents = useAppSelector( + (state) => state.userAppData?.processedGiftWraps + ) + + /** + * Fetches user application data based on user's public key. + * + * @returns The user application data or null if an error occurs or no data is found. + */ + const getUsersAppData = useCallback(async (): Promise => { + if (!usersPubkey) return null + + // Get an instance of the NostrController + const nostrController = NostrController.getInstance() + + // Decryption can fail down in the code if extension options changed + // Forcefully log out the user if we detect missmatch between pubkeys + if (usersPubkey !== (await nostrController.capturePublicKey())) { + return null + } + + // Generate an identifier for the user's nip78 + const dTag = await getDTagForUserAppData() + if (!dTag) return null + + // Define a filter for fetching events + const filter: NDKFilter = { + kinds: [NDKKind.AppSpecificData], + authors: [usersPubkey], + '#d': [dTag] + } + + const encryptedContent = await fetchEvent(filter, { + cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY + }) + .then((event) => { + if (event) return event.content + + // If no event is found, return an empty stringified object + return '{}' + }) + .catch((err) => { + // Log error and show a toast notification if fetching event fails + console.log(`An error occurred in finding kind 30078 event`, err) + toast.error( + 'An error occurred in finding kind 30078 event for data storage' + ) + return null + }) + + // Return null if encrypted content retrieval fails + if (!encryptedContent) return null + + // Handle case where the encrypted content is an empty object + if (encryptedContent === '{}') { + // Generate ephemeral key pair + const secret = generateSecretKey() + const pubKey = getPublicKey(secret) + + return { + sigits: {}, + processedGiftWraps: [], + blossomUrls: [], + keyPair: { + private: bytesToHex(secret), + public: pubKey + } + } + } + + // Decrypt the encrypted content + const decrypted = await nostrController + .nip04Decrypt(usersPubkey, encryptedContent) + .catch((err) => { + // Log error and show a toast notification if decryption fails + console.log('An error occurred while decrypting app data', err) + toast.error('An error occurred while decrypting app data') + return null + }) + + // Return null if decryption fails + if (!decrypted) return null + + // Parse the decrypted content + const parsedContent = await parseJson<{ + blossomUrls: string[] + keyPair: Keys + }>(decrypted).catch((err) => { + // Log error and show a toast notification if parsing fails + console.log( + 'An error occurred in parsing the content of kind 30078 event', + err + ) + toast.error( + 'An error occurred in parsing the content of kind 30078 event' + ) + return null + }) + + // Return null if parsing fails + if (!parsedContent) return null + + const { blossomUrls, keyPair } = parsedContent + + // Return null if no blossom URLs are found + if (blossomUrls.length === 0) return null + + // Fetch additional user app data from the first blossom URL + const dataFromBlossom = await getUserAppDataFromBlossom( + blossomUrls[0], + keyPair.private + ) + + // Return null if fetching data from blossom fails + if (!dataFromBlossom) return null + + const { sigits, processedGiftWraps } = dataFromBlossom + + // Return the final user application data + return { + blossomUrls, + keyPair, + sigits, + processedGiftWraps + } + }, [usersPubkey, fetchEvent]) + + const updateUsersAppData = useCallback( + async (metaArray: Meta[]) => { + if (!appData || !appData.keyPair || !usersPubkey) return null + + const sigits = _.cloneDeep(appData.sigits) + let isUpdated = false + + for (const meta of metaArray) { + const createSignatureEvent = await parseJson( + meta.createSignature + ).catch((err) => { + console.log('Error in parsing the createSignature event:', err) + toast.error( + err.message || + 'Error occurred in parsing the create signature event' + ) + return null + }) + + if (!createSignatureEvent) continue + + const id = createSignatureEvent.id + + // Check if sigit already exists + if (id in sigits) { + // Update meta only if incoming meta is more recent + const existingMeta = sigits[id] + if (existingMeta.modifiedAt < meta.modifiedAt) { + sigits[id] = meta + isUpdated = true + } + } else { + sigits[id] = meta + isUpdated = true + } + } + + if (!isUpdated) return null + + const blossomUrls = [...appData.blossomUrls] + + const newBlossomUrl = await uploadUserAppDataToBlossom( + sigits, + appData.processedGiftWraps, + appData.keyPair.private + ).catch((err) => { + console.log( + 'Error uploading user app data file to Blossom server:', + err + ) + toast.error( + 'Error occurred in uploading user app data file to Blossom server' + ) + return null + }) + + if (!newBlossomUrl) return null + + // Insert new blossom URL at the start of the array + blossomUrls.unshift(newBlossomUrl) + + // Keep only the last 10 Blossom URLs, delete older ones + if (blossomUrls.length > 10) { + const filesToDelete = blossomUrls.splice(10) + filesToDelete.forEach((url) => { + deleteBlossomFile(url, appData.keyPair!.private).catch((err) => { + console.log('Error removing old file from Blossom server:', err) + }) + }) + } + + // Encrypt content for storing in kind 30078 event + const nostrController = NostrController.getInstance() + const encryptedContent = await nostrController + .nip04Encrypt( + usersPubkey, + JSON.stringify({ + blossomUrls, + keyPair: appData.keyPair + }) + ) + .catch((err) => { + console.log('Error encrypting content for app data:', err) + toast.error(err.message || 'Error encrypting content for app data') + return null + }) + + if (!encryptedContent) return null + + // Generate the identifier for user's appData event + const dTag = await getDTagForUserAppData() + if (!dTag) return null + + const updatedEvent: UnsignedEvent = { + kind: kinds.Application, + pubkey: usersPubkey, + created_at: unixNow(), + tags: [['d', dTag]], + content: encryptedContent + } + + const signedEvent = await nostrController + .signEvent(updatedEvent) + .catch((err) => { + console.log('Error signing event:', err) + toast.error(err.message || 'Error signing event') + return null + }) + + if (!signedEvent) return null + + const ndkEvent = new NDKEvent(ndk, signedEvent) + const publishResult = await publish(ndkEvent) + + if (publishResult.length === 0 || !publishResult) { + toast.error('Unexpected error occurred in publishing updated app data') + return null + } + + console.count('updateUserAppData useNDK') + + // Update Redux store + dispatch( + updateUserAppDataAction({ + sigits, + blossomUrls, + processedGiftWraps: [...appData.processedGiftWraps], + keyPair: { + ...appData.keyPair + } + }) + ) + + return signedEvent + }, + [appData, dispatch, ndk, publish, usersPubkey] + ) + + const processReceivedEvents = useCallback( + async (events: NDKEvent[], difficulty: number = 5) => { + if (!processedEvents) return + + const validMetaArray: Meta[] = [] // Array to store valid Meta objects + const updatedProcessedEvents = [...processedEvents] // Keep track of processed event IDs + + for (const event of events) { + // Skip already processed events + if (processedEvents.includes(event.id)) continue + + // Validate PoW + const leadingZeroes = countLeadingZeroes(event.id) + if (leadingZeroes < difficulty) continue + + // Decrypt the content of the gift wrap event + const nostrController = NostrController.getInstance() + const decrypted = await nostrController + .nip44Decrypt(event.pubkey, event.content) + .catch((err) => { + console.log('An error occurred in decrypting event content', err) + return null + }) + + if (!decrypted) continue + + const internalUnsignedEvent = await parseJson( + decrypted + ).catch((err) => { + console.log( + 'An error occurred in parsing the internal unsigned event', + err + ) + return null + }) + + if (!internalUnsignedEvent || internalUnsignedEvent.kind !== 938) + continue + + const parsedContent = await parseJson( + internalUnsignedEvent.content + ).catch((err) => { + console.log('An error occurred in parsing event content', err) + return null + }) + + if (!parsedContent) continue + + let meta: Meta + + if (isSigitNotification(parsedContent)) { + const notification = parsedContent + if (!notification.keys || !usersPubkey) continue + + let encryptionKey: string | undefined + const { sender, keys } = notification.keys + const usersNpub = hexToNpub(usersPubkey) + + if (usersNpub in keys) { + encryptionKey = await nostrController + .nip04Decrypt(sender, keys[usersNpub]) + .catch((err) => { + console.log( + 'An error occurred in decrypting encryption key', + err + ) + return undefined + }) + } + + try { + meta = await fetchMetaFromFileStorage( + notification.metaUrl, + encryptionKey + ) + } catch (error) { + console.error( + 'An error occurred fetching meta file from storage', + error + ) + continue + } + } else { + meta = parsedContent + } + + validMetaArray.push(meta) // Add valid Meta to the array + updatedProcessedEvents.push(event.id) // Mark event as processed + } + + // Update processed events in the Redux store + dispatch(updateProcessedGiftWraps(updatedProcessedEvents)) + + // Pass the array of Meta objects to updateUsersAppData + if (validMetaArray.length > 0) { + await updateUsersAppData(validMetaArray) + } + }, + [dispatch, processedEvents, updateUsersAppData, usersPubkey] + ) + + const subscribeForSigits = useCallback( + async (pubkey: string) => { + // Define the filter for the subscription + const filter: NDKFilter = { + kinds: [1059 as NDKKind], + '#p': [pubkey] + } + + // Process the received event synchronously + const events = await fetchEventsFromUserRelays( + filter, + pubkey, + UserRelaysType.Read, + { + cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY + } + ) + + await processReceivedEvents(events) + }, + [fetchEventsFromUserRelays, processReceivedEvents] + ) + + /** + * Function to send a notification to a specified receiver. + * @param receiver - The recipient's public key. + * @param notification - Url pointing to metadata associated with the notification on blossom and keys to decrypt. + */ + const sendNotification = useCallback( + async (receiver: string, notification: SigitNotification) => { + if (!usersPubkey) return + + // Create an unsigned event object with the provided metadata + const unsignedEvent: UnsignedEvent = { + kind: 938, + pubkey: usersPubkey, + content: JSON.stringify(notification), + tags: [], + created_at: unixNow() + } + + // Wrap the unsigned event with the receiver's information + const wrappedEvent = createWrap(unsignedEvent, receiver) + + // Publish the notification event to the recipient's read relays + const ndkEvent = new NDKEvent(ndk, wrappedEvent) + + const ndkRelayList = await getNDKRelayList(receiver) + + const readRelayUrls: string[] = [] + + if (ndkRelayList?.readRelayUrls) { + readRelayUrls.push(...ndkRelayList.readRelayUrls) + } + + if (!readRelayUrls.includes(SIGIT_RELAY)) { + readRelayUrls.push(SIGIT_RELAY) + } + + await ndkEvent + .publish(NDKRelaySet.fromRelayUrls(readRelayUrls, ndk, true)) + .then((publishedOnRelays) => { + if (publishedOnRelays.size === 0) { + throw new Error('Could not publish to any relay') + } + + return publishedOnRelays + }) + .catch((err) => { + // Log an error if publishing the notification event fails + console.log( + `An error occurred while publishing notification event for ${hexToNpub(receiver)}`, + err + ) + throw err + }) + }, + [ndk, usersPubkey, getNDKRelayList] + ) + + return { + getUsersAppData, + subscribeForSigits, + updateUsersAppData, + sendNotification + } +} diff --git a/src/hooks/useNDKContext.ts b/src/hooks/useNDKContext.ts new file mode 100644 index 0000000..9d502fc --- /dev/null +++ b/src/hooks/useNDKContext.ts @@ -0,0 +1,13 @@ +import { NDKContext, NDKContextType } from '../contexts/NDKContext' +import { useContext } from 'react' + +export const useNDKContext = () => { + const ndkContext = useContext(NDKContext) + + if (!ndkContext) + throw new Error( + 'NDKContext should not be used in out component tree hierarchy' + ) + + return { ...ndkContext } as NDKContextType +} diff --git a/src/hooks/useProfileMetadata.tsx b/src/hooks/useProfileMetadata.tsx index f746f0d..9532bb3 100644 --- a/src/hooks/useProfileMetadata.tsx +++ b/src/hooks/useProfileMetadata.tsx @@ -1,33 +1,18 @@ import { useEffect, useState } from 'react' -import { ProfileMetadata } from '../types/profile' -import { MetadataController } from '../controllers/MetadataController' -import { Event, kinds } from 'nostr-tools' + +import { NDKUserProfile } from '@nostr-dev-kit/ndk' +import { useNDKContext } from './useNDKContext' export const useProfileMetadata = (pubkey: string) => { - const [profileMetadata, setProfileMetadata] = useState() + const { findMetadata } = useNDKContext() + + const [userProfile, setUserProfile] = useState() useEffect(() => { - const metadataController = MetadataController.getInstance() - const handleMetadataEvent = (event: Event) => { - const metadataContent = - metadataController.extractProfileMetadataContent(event) - - if (metadataContent) { - setProfileMetadata(metadataContent) - } - } - if (pubkey) { - metadataController.on(pubkey, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(event) - } - }) - - metadataController - .findMetadata(pubkey) - .then((metadataEvent) => { - if (metadataEvent) handleMetadataEvent(metadataEvent) + findMetadata(pubkey) + .then((profile) => { + if (profile) setUserProfile(profile) }) .catch((err) => { console.error( @@ -36,11 +21,7 @@ export const useProfileMetadata = (pubkey: string) => { ) }) } + }, [pubkey, findMetadata]) - return () => { - metadataController.off(pubkey, handleMetadataEvent) - } - }, [pubkey]) - - return profileMetadata + return userProfile } diff --git a/src/hooks/useSigitMeta.tsx b/src/hooks/useSigitMeta.tsx index c794496..2026621 100644 --- a/src/hooks/useSigitMeta.tsx +++ b/src/hooks/useSigitMeta.tsx @@ -1,10 +1,5 @@ import { useEffect, useState } from 'react' -import { - CreateSignatureEventContent, - DocSignatureEvent, - Meta, - SignedEventContent -} from '../types' +import { DocSignatureEvent, Meta, SignedEventContent, FlatMeta } from '../types' import { Mark } from '../types/mark' import { fromUnixTimestamp, @@ -16,49 +11,10 @@ import { } from '../utils' import { toast } from 'react-toastify' import { verifyEvent } from 'nostr-tools' -import { Event } from 'nostr-tools' import store from '../store/store' import { NostrController } from '../controllers' import { MetaParseError } from '../types/errors/MetaParseError' - -/** - * Flattened interface that combines properties `Meta`, `CreateSignatureEventContent`, - * and `Event` (event's fields are made optional and pubkey and created_at replaced with our versions) - */ -export interface FlatMeta - extends Meta, - CreateSignatureEventContent, - Partial> { - // Remove pubkey and use submittedBy as `npub1${string}` - submittedBy?: `npub1${string}` - - // Optional field only present on exported sigits - // Exporting adds user's pubkey - exportedBy?: `npub1${string}` - - // Remove created_at and replace with createdAt - createdAt?: number - - // Validated create signature event - isValid: boolean - - // Decryption - encryptionKey: string | null - - // Parsed Document Signatures - parsedSignatureEvents: { - [signer: `npub1${string}`]: DocSignatureEvent - } - - // Calculated completion time - completedAt?: number - - // Calculated status fields - signedStatus: SigitStatus - signersStatus: { - [signer: `npub1${string}`]: SignStatus - } -} +import { MARK_TYPE_CONFIG } from '../components/MarkTypeStrategy/MarkStrategy' /** * Custom use hook for parsing the Sigit Meta @@ -70,8 +26,8 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { const [kind, setKind] = useState() const [tags, setTags] = useState() const [createdAt, setCreatedAt] = useState() - const [submittedBy, setSubmittedBy] = useState<`npub1${string}`>() // submittedBy, pubkey from nostr event - const [exportedBy, setExportedBy] = useState<`npub1${string}`>() // pubkey from export signature nostr event + const [submittedBy, setSubmittedBy] = useState() // submittedBy, pubkey from nostr event (hex) + const [exportedBy, setExportedBy] = useState() // pubkey from export signature nostr event (hex) const [id, setId] = useState() const [sig, setSig] = useState() @@ -97,25 +53,23 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { [signer: `npub1${string}`]: SignStatus }>({}) - const [encryptionKey, setEncryptionKey] = useState(null) + const [encryptionKey, setEncryptionKey] = useState() useEffect(() => { if (!meta) return ;(async function () { try { if (meta.exportSignature) { - const exportSignatureEvent = await parseNostrEvent( - meta.exportSignature - ) + const exportSignatureEvent = parseNostrEvent(meta.exportSignature) if ( verifyEvent(exportSignatureEvent) && exportSignatureEvent.pubkey ) { - setExportedBy(exportSignatureEvent.pubkey as `npub1${string}`) + setExportedBy(exportSignatureEvent.pubkey) } } - const createSignatureEvent = await parseNostrEvent(meta.createSignature) + const createSignatureEvent = parseNostrEvent(meta.createSignature) const { kind, tags, created_at, pubkey, id, sig, content } = createSignatureEvent @@ -125,12 +79,12 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { setTags(tags) // created_at in nostr events are stored in seconds setCreatedAt(fromUnixTimestamp(created_at)) - setSubmittedBy(pubkey as `npub1${string}`) + setSubmittedBy(pubkey) setId(id) setSig(sig) const { title, signers, viewers, fileHashes, markConfig, zipUrl } = - await parseCreateSignatureEventContent(content) + parseCreateSignatureEventContent(content) setTitle(title) setSigners(signers) @@ -139,6 +93,7 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { setMarkConfig(markConfig) setZipUrl(zipUrl) + let encryptionKey: string | undefined if (meta.keys) { const { sender, keys } = meta.keys // Retrieve the user's public key from the state @@ -156,13 +111,13 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { 'An error occurred in decrypting encryption key', err ) - return null + return undefined }) + encryptionKey = decrypted setEncryptionKey(decrypted) } } - // Temp. map to hold events and signers const parsedSignatureEventsMap = new Map< `npub1${string}`, @@ -204,13 +159,40 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { } } - parsedSignatureEventsMap.forEach((event, npub) => { + for (const [npub, event] of parsedSignatureEventsMap) { const isValidSignature = verifyEvent(event) if (isValidSignature) { // get the signature of prev signer from the content of current signers signedEvent const prevSignersSig = getPrevSignerSig(npub) + try { const obj: SignedEventContent = JSON.parse(event.content) + + // Signature object can include values that need to be fetched and decrypted + for (let i = 0; i < obj.marks.length; i++) { + const m = obj.marks[i] + + try { + const { fetchAndDecrypt } = MARK_TYPE_CONFIG[m.type] || {} + if ( + typeof fetchAndDecrypt === 'function' && + m.value && + encryptionKey + ) { + const decrypted = await fetchAndDecrypt( + m.value, + encryptionKey + ) + obj.marks[i].value = decrypted + } + } catch (error) { + console.error( + `Error during mark fetchAndDecrypt phase`, + error + ) + } + } + parsedSignatureEventsMap.set(npub, { ...event, parsedContent: obj @@ -226,7 +208,7 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { signerStatusMap.set(npub as `npub1${string}`, SignStatus.Invalid) } } - }) + } signers .filter((s) => !parsedSignatureEventsMap.has(s)) @@ -276,6 +258,7 @@ export const useSigitMeta = (meta: Meta): FlatMeta => { createSignature: meta?.createSignature, docSignatures: meta?.docSignatures, keys: meta?.keys, + timestamps: meta?.timestamps, isValid, kind, tags, diff --git a/src/layouts/Main.tsx b/src/layouts/Main.tsx index 19ac4d9..85daf75 100644 --- a/src/layouts/Main.tsx +++ b/src/layouts/Main.tsx @@ -1,40 +1,49 @@ -import { Event, getPublicKey, kinds, nip19 } from 'nostr-tools' import { useCallback, useEffect, useRef, useState } from 'react' import { Outlet, useNavigate, useSearchParams } from 'react-router-dom' + +import { getPublicKey, nip19 } from 'nostr-tools' + +import { init as initNostrLogin } from 'nostr-login' +import { NostrLoginAuthOptions } from 'nostr-login/dist/types' + import { AppBar } from '../components/AppBar/AppBar' import { LoadingSpinner } from '../components/LoadingSpinner' + +import { NostrController } from '../controllers' + import { - AuthController, - MetadataController, - NostrController -} from '../controllers' + useAppDispatch, + useAppSelector, + useAuth, + useLogout, + useNDK, + useNDKContext +} from '../hooks' + import { restoreState, - setMetadataEvent, + setUserProfile, updateKeyPair, updateLoginMethod, updateNostrLoginAuthMethod, - updateUserAppData + updateUserAppData, + setUserRobotImage } from '../store/actions' -import { setUserRobotImage } from '../store/userRobotImage/action' -import { - getRoboHashPicture, - getUsersAppData, - loadState, - subscribeForSigits -} from '../utils' -import { useAppDispatch, useAppSelector } from '../hooks' -import styles from './style.module.scss' -import { useLogout } from '../hooks/useLogout' import { LoginMethod } from '../store/auth/types' -import { NostrLoginAuthOptions } from 'nostr-login/dist/types' -import { init as initNostrLogin } from 'nostr-login' + +import { getRoboHashPicture, loadState } from '../utils' + +import styles from './style.module.scss' export const MainLayout = () => { const [searchParams, setSearchParams] = useSearchParams() const navigate = useNavigate() const dispatch = useAppDispatch() const logout = useLogout() + const { findMetadata } = useNDKContext() + const { authAndGetMetadataAndRelaysMap } = useAuth() + const { getUsersAppData, subscribeForSigits } = useNDK() + const [isLoading, setIsLoading] = useState(true) const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState(`Loading App`) const isLoggedIn = useAppSelector((state) => state.auth?.loggedIn) @@ -58,14 +67,12 @@ export const MainLayout = () => { } const login = useCallback(async () => { - const nostrController = NostrController.getInstance() - const authController = new AuthController() - const pubkey = await nostrController.capturePublicKey() - dispatch(updateLoginMethod(LoginMethod.nostrLogin)) - const redirectPath = - await authController.authAndGetMetadataAndRelaysMap(pubkey) + const nostrController = NostrController.getInstance() + const pubkey = await nostrController.capturePublicKey() + + const redirectPath = await authAndGetMetadataAndRelaysMap(pubkey) if (redirectPath) { navigateAfterLogin(redirectPath) @@ -105,13 +112,10 @@ export const MainLayout = () => { ) dispatch(updateLoginMethod(LoginMethod.privateKey)) - const authController = new AuthController() - authController - .authAndGetMetadataAndRelaysMap(publickey) - .catch((err) => { - console.error('Error occurred in authentication: ' + err) - return null - }) + authAndGetMetadataAndRelaysMap(publickey).catch((err) => { + console.error('Error occurred in authentication: ' + err) + return null + }) } catch (err) { console.error(`Error decoding the nsec. ${err}`) } @@ -134,7 +138,15 @@ export const MainLayout = () => { initNostrLogin({ methods: ['connect', 'extension', 'local'], noBanner: true, - onAuth: handleNostrAuth + onAuth: handleNostrAuth, + outboxRelays: [ + 'wss://purplepag.es', + 'wss://relay.nos.social', + 'wss://user.kindpag.es', + 'wss://relay.damus.io', + 'wss://nos.lol', + 'wss://relay.sigit.io' + ] }).catch((error) => { console.error('Failed to initialize Nostr-Login', error) }) @@ -143,8 +155,6 @@ export const MainLayout = () => { }, [dispatch]) useEffect(() => { - const metadataController = MetadataController.getInstance() - const restoredState = loadState() if (restoredState) { dispatch(restoreState(restoredState)) @@ -154,19 +164,8 @@ export const MainLayout = () => { if (loggedIn) { if (!loginMethod || !usersPubkey) return logout() - // Update user profile metadata, old state might be outdated - const handleMetadataEvent = (event: Event) => { - dispatch(setMetadataEvent(event)) - } - - metadataController.on(usersPubkey, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(event) - } - }) - - metadataController.findMetadata(usersPubkey).then((metadataEvent) => { - if (metadataEvent) handleMetadataEvent(metadataEvent) + findMetadata(usersPubkey).then((profile) => { + dispatch(setUserProfile(profile)) }) } else { setIsLoading(false) @@ -193,7 +192,7 @@ export const MainLayout = () => { hasSubscribed.current = true } } - }, [authState, isLoggedIn, usersAppData]) + }, [authState, isLoggedIn, usersAppData, subscribeForSigits]) /** * When authState change user logged in / or app reloaded diff --git a/src/main.tsx b/src/main.tsx index a8b1898..6b6b748 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,13 +11,13 @@ import './index.css' import store from './store/store.ts' import { theme } from './theme' import { saveState } from './utils' +import { NDKContextProvider } from './contexts/NDKContext' store.subscribe( _.throttle(() => { saveState({ auth: store.getState().auth, - metadata: store.getState().metadata, - userRobotImage: store.getState().userRobotImage, + user: store.getState().user, relays: store.getState().relays }) }, 1000) @@ -28,7 +28,9 @@ ReactDOM.createRoot(document.getElementById('root')!).render( - + + + diff --git a/src/pages/create/index.tsx b/src/pages/create/index.tsx index 40da254..686f080 100644 --- a/src/pages/create/index.tsx +++ b/src/pages/create/index.tsx @@ -1,10 +1,15 @@ import styles from './style.module.scss' -import { Button, FormHelperText, TextField, Tooltip } from '@mui/material' +import { + Box, + Button, + CircularProgress, + FormHelperText, + TextField, + Tooltip +} from '@mui/material' import type { Identifier, XYCoord } from 'dnd-core' -import saveAs from 'file-saver' import JSZip from 'jszip' -import { Event, kinds } from 'nostr-tools' -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { DndProvider, useDrag, useDrop } from 'react-dnd' import { MultiBackend } from 'react-dnd-multi-backend' import { HTML5toTouch } from 'rdndmb-html5-to-touch' @@ -13,13 +18,16 @@ import { useLocation, useNavigate } from 'react-router-dom' import { toast } from 'react-toastify' import { LoadingSpinner } from '../../components/LoadingSpinner' import { UserAvatar } from '../../components/UserAvatar' -import { MetadataController, NostrController } from '../../controllers' -import { appPrivateRoutes } from '../../routes' +import { NostrController } from '../../controllers' +import { appPrivateRoutes, appPublicRoutes } from '../../routes' import { CreateSignatureEventContent, + KeyboardCode, Meta, - ProfileMetadata, + SigitNotification, + SignedEvent, User, + UserRelaysType, UserRole } from '../../types' import { @@ -30,18 +38,16 @@ import { generateKeysFile, getHash, hexToNpub, - isOnline, unixNow, npubToHex, queryNip05, - sendNotification, signEventForMetaFile, - updateUsersAppData, uploadToFileStorage, DEFAULT_TOOLBOX, settleAllFullfilfedPromises, sendPrivateDirectMessage, - parseNostrEvent + parseNostrEvent, + uploadMetaToFileStorage } from '../../utils' import { Container } from '../../components/Container' import fileListStyles from '../../components/FileList/style.module.scss' @@ -51,6 +57,7 @@ import { Mark } from '../../types/mark.ts' import { StickySideColumns } from '../../layouts/StickySideColumns.tsx' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { + faDownload, faEllipsis, faEye, faFile, @@ -58,17 +65,32 @@ import { faGripLines, faPen, faPlus, + faSearch, faToolbox, faTrash, faUpload } from '@fortawesome/free-solid-svg-icons' import { getSigitFile, SigitFile } from '../../utils/file.ts' -import _ from 'lodash' +import { generateTimestamp } from '../../utils/opentimestamps.ts' +import { Autocomplete } from '@mui/material' +import _, { truncate } from 'lodash' import { SendDMError } from '../../types/errors/SendDMError.ts' +import * as React from 'react' +import { AvatarIconButton } from '../../components/UserAvatarIconButton' +import { NDKUserProfile, NostrEvent } from '@nostr-dev-kit/ndk' +import { useNDKContext } from '../../hooks/useNDKContext.ts' +import { useNDK } from '../../hooks/useNDK.ts' +import { useImmer } from 'use-immer' +import { ButtonUnderline } from '../../components/ButtonUnderline/index.tsx' + +type FoundUser = NostrEvent & { npub: string } export const CreatePage = () => { const navigate = useNavigate() const location = useLocation() + const { findMetadata, fetchEventsFromUserRelays } = useNDKContext() + const { updateUsersAppData, sendNotification } = useNDK() + const { uploadedFiles } = location.state || {} const [currentFile, setCurrentFile] = useState() const isActive = (file: File) => file.name === currentFile?.name @@ -78,7 +100,7 @@ export const CreatePage = () => { const [title, setTitle] = useState(`sigit_${formatTimestamp(Date.now())}`) - const [selectedFiles, setSelectedFiles] = useState([]) + const [selectedFiles, setSelectedFiles] = useState([...uploadedFiles]) const fileInputRef = useRef(null) const handleUploadButtonClick = () => { if (fileInputRef.current) { @@ -87,32 +109,176 @@ export const CreatePage = () => { } const [userInput, setUserInput] = useState('') - const handleInputKeyDown = (event: React.KeyboardEvent) => { - if (event.code === 'Enter' || event.code === 'NumpadEnter') { - event.preventDefault() - handleAddUser() - } - } - const [userRole, setUserRole] = useState(UserRole.signer) + const [userSearchInput, setUserSearchInput] = useState('') + + const [userRole] = useState(UserRole.signer) const [error, setError] = useState() const [users, setUsers] = useState([]) const signers = users.filter((u) => u.role === UserRole.signer) const viewers = users.filter((u) => u.role === UserRole.viewer) - const usersPubkey = useAppSelector((state) => state.auth.usersPubkey) + const usersPubkey = useAppSelector((state) => state.auth.usersPubkey)! const nostrController = NostrController.getInstance() - const [metadata, setMetadata] = useState<{ [key: string]: ProfileMetadata }>( - {} - ) - const [drawnFiles, setDrawnFiles] = useState([]) + const [userProfiles, setUserProfiles] = useState<{ + [key: string]: NDKUserProfile + }>({}) + + const [drawnFiles, updateDrawnFiles] = useImmer([]) const [parsingPdf, setIsParsing] = useState(false) + + const searchFieldRef = useRef(null) + + const [selectedTool, setSelectedTool] = useState() + + const [foundUsers, setFoundUsers] = useState([]) + const [searchUsersLoading, setSearchUsersLoading] = useState(false) + const [pastedUserNpubOrNip05, setPastedUserNpubOrNip05] = useState< + string | undefined + >() + + /** + * Fired when user select + */ + const handleSearchUserChange = useCallback( + (_event: React.SyntheticEvent, value: string | FoundUser | null) => { + if (typeof value === 'object') { + const ndkEvent = value as FoundUser + if (ndkEvent?.pubkey) { + setUserInput(hexToNpub(ndkEvent.pubkey)) + } + } + }, + [setUserInput] + ) + + const handleSearchUserNip05 = async ( + nip05: string + ): Promise => { + const { pubkey } = await queryNip05(nip05).catch((err) => { + console.error(err) + return { pubkey: null } + }) + + return pubkey + } + + const handleSearchUsers = async (searchValue?: string) => { + const searchString = searchValue || userSearchInput || undefined + + if (!searchString) return + + setSearchUsersLoading(true) + + const searchTerm = searchString.trim() + + fetchEventsFromUserRelays( + { + kinds: [0], + search: searchTerm + }, + usersPubkey, + UserRelaysType.Write + ) + .then((events) => { + const nostrEvents = events.map((event) => event.rawEvent()) + + const fineFilteredEvents = nostrEvents + .filter((event) => { + const lowercaseContent = event.content.toLowerCase() + + return ( + lowercaseContent.includes( + `"name":"${searchTerm.toLowerCase()}"` + ) || + lowercaseContent.includes( + `"display_name":"${searchTerm.toLowerCase()}"` + ) || + lowercaseContent.includes( + `"username":"${searchTerm.toLowerCase()}"` + ) || + lowercaseContent.includes(`"nip05":"${searchTerm.toLowerCase()}"`) + ) + }) + .reduce((uniqueEvents, event) => { + if (!uniqueEvents.some((e) => e.pubkey === event.pubkey)) { + uniqueEvents.push({ + ...event, + npub: hexToNpub(event.pubkey) + }) + } + return uniqueEvents + }, [] as FoundUser[]) + + console.info('fineFilteredEvents', fineFilteredEvents) + setFoundUsers(fineFilteredEvents) + + if (!fineFilteredEvents.length) + toast.info('No user found with the provided search term') + }) + .catch((error) => { + console.error(error) + }) + .finally(() => { + setSearchUsersLoading(false) + }) + } + + useEffect(() => { + setTimeout(() => { + if (foundUsers.length) { + if (searchFieldRef.current) { + searchFieldRef.current.blur() + searchFieldRef.current.focus() + } + } + }) + }, [foundUsers]) + + const handleInputKeyDown = async ( + event: React.KeyboardEvent + ) => { + if ( + event.code === KeyboardCode.Enter || + event.code === KeyboardCode.NumpadEnter + ) { + event.preventDefault() + + // If pasted user npub of nip05 is present, we just add the user to the counterparts list + if (pastedUserNpubOrNip05) { + setUserInput(pastedUserNpubOrNip05) + setPastedUserNpubOrNip05(undefined) + } else { + // Otherwize if search already provided some results, user must manually click the search button + if (!foundUsers.length) { + // If it's NIP05 (includes @ or is a valid domain) send request to .well-known + const domainRegex = /^[a-zA-Z0-9@.-]+\.[a-zA-Z]{2,}$/ + if (domainRegex.test(userSearchInput)) { + setSearchUsersLoading(true) + + const pubkey = await handleSearchUserNip05(userSearchInput) + + setSearchUsersLoading(false) + + if (pubkey) { + setUserInput(userSearchInput) + } else { + toast.error(`No user found with the NIP05: ${userSearchInput}`) + } + } else { + handleSearchUsers() + } + } + } + } + } + useEffect(() => { if (selectedFiles) { /** - * Reads the binary files and converts to internal file type + * Reads the binary files and converts to an internal file type * and sets to a state (adds images if it's a PDF) */ const parsePages = async () => { @@ -120,8 +286,28 @@ export const CreatePage = () => { selectedFiles, getSigitFile ) + updateDrawnFiles((draft) => { + // Existing files are untouched - setDrawnFiles(files) + // Handle removed files + // Remove in reverse to avoid index issues + for (let i = draft.length - 1; i >= 0; i--) { + if ( + !files.some( + (f) => f.name === draft[i].name && f.size === draft[i].size + ) + ) { + draft.splice(i, 1) + } + } + + // Add new files + files.forEach((f) => { + if (!draft.some((d) => d.name === f.name && d.size === f.size)) { + draft.push(f) + } + }) + }) } setIsParsing(true) @@ -130,9 +316,7 @@ export const CreatePage = () => { setIsParsing(false) }) } - }, [selectedFiles]) - - const [selectedTool, setSelectedTool] = useState() + }, [selectedFiles, updateDrawnFiles]) /** * Changes the drawing tool @@ -150,29 +334,15 @@ export const CreatePage = () => { useEffect(() => { users.forEach((user) => { - if (!(user.pubkey in metadata)) { - const metadataController = MetadataController.getInstance() - - const handleMetadataEvent = (event: Event) => { - const metadataContent = - metadataController.extractProfileMetadataContent(event) - if (metadataContent) - setMetadata((prev) => ({ - ...prev, - [user.pubkey]: metadataContent - })) - } - - metadataController.on(user.pubkey, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(event) - } - }) - - metadataController - .findMetadata(user.pubkey) - .then((metadataEvent) => { - if (metadataEvent) handleMetadataEvent(metadataEvent) + if (!(user.pubkey in userProfiles)) { + findMetadata(user.pubkey) + .then((profile) => { + if (profile) { + setUserProfiles((prev) => ({ + ...prev, + [user.pubkey]: profile + })) + } }) .catch((err) => { console.error( @@ -182,13 +352,7 @@ export const CreatePage = () => { }) } }) - }, [metadata, users]) - - useEffect(() => { - if (uploadedFiles) { - setSelectedFiles([...uploadedFiles]) - } - }, [uploadedFiles]) + }, [userProfiles, users, findMetadata]) useEffect(() => { if (usersPubkey) { @@ -206,7 +370,7 @@ export const CreatePage = () => { } }, [usersPubkey]) - const handleAddUser = async () => { + const handleAddUser = useCallback(async () => { setError(undefined) const addUser = (pubkey: string) => { @@ -248,6 +412,8 @@ export const CreatePage = () => { const input = userInput.toLowerCase() + setUserSearchInput('') + if (input.startsWith('npub')) { return handleAddNpubUser(input) } @@ -297,7 +463,20 @@ export const CreatePage = () => { } return } - } + }, [ + userInput, + userRole, + setError, + setUsers, + setUserSearchInput, + setIsLoading, + setLoadingSpinnerDesc, + setUserInput + ]) + + useEffect(() => { + if (userInput?.length > 0) handleAddUser() + }, [handleAddUser, userInput]) const handleUserRoleChange = (role: UserRole, pubkey: string) => { setUsers((prevUsers) => @@ -328,7 +507,7 @@ export const CreatePage = () => { }) }) }) - setDrawnFiles(drawnFilesCopy) + updateDrawnFiles(drawnFilesCopy) } /** @@ -352,11 +531,16 @@ export const CreatePage = () => { const files = Array.from(event.target.files) // Remove duplicates based on the file.name - setSelectedFiles((p) => - [...p, ...files].filter( + setSelectedFiles((p) => { + const unique = [...p, ...files].filter( (file, i, array) => i === array.findIndex((t) => t.name === file.name) ) - ) + navigate('.', { + state: { uploadedFiles: unique }, + replace: true + }) + return unique + }) } } @@ -370,9 +554,14 @@ export const CreatePage = () => { ) => { event.stopPropagation() - setSelectedFiles((prevFiles) => - prevFiles.filter((file) => file.name !== fileToRemove.name) - ) + setSelectedFiles((prevFiles) => { + const files = prevFiles.filter((file) => file.name !== fileToRemove.name) + navigate('.', { + state: { uploadedFiles: files }, + replace: true + }) + return files + }) } // Validate inputs before proceeding @@ -450,8 +639,8 @@ export const CreatePage = () => { width: drawnField.width }, npub: drawnField.counterpart, - pdfFileHash: fileHash, - fileName: file.name + fileName: file.name, + fileHash } }) }) || [] @@ -506,10 +695,18 @@ export const CreatePage = () => { type: 'application/sigit' }) - const firstSigner = users.filter((user) => user.role === UserRole.signer)[0] - + const userSet = new Set() + const nostrController = NostrController.getInstance() + const pubkey = await nostrController.capturePublicKey() + userSet.add(pubkey) + signers.forEach((signer) => { + userSet.add(signer.pubkey) + }) + viewers.forEach((viewer) => { + userSet.add(viewer.pubkey) + }) const keysFileContent = await generateKeysFile( - [firstSigner.pubkey], + Array.from(userSet), encryptionKey ) if (!keysFileContent) return null @@ -561,30 +758,6 @@ export const CreatePage = () => { .catch(handleUploadError) } - // Manage offline scenarios for signing or viewing the file - const handleOfflineFlow = async ( - encryptedArrayBuffer: ArrayBuffer, - encryptionKey: string - ) => { - const finalZipFile = await createFinalZipFile( - encryptedArrayBuffer, - encryptionKey - ) - - if (!finalZipFile) { - setIsLoading(false) - return - } - - saveAs(finalZipFile, `request-${unixNow()}.sigit.zip`) - - // If user is the next signer, we can navigate directly to sign page - if (signers[0].pubkey === usersPubkey) { - navigate(appPrivateRoutes.sign, { state: { uploadedZip: finalZipFile } }) - } - setIsLoading(false) - } - const generateFilesZip = async (): Promise => { const zip = new JSZip() selectedFiles.forEach((file) => { @@ -616,7 +789,7 @@ export const CreatePage = () => { title } - setLoadingSpinnerDesc('Signing nostr event for create signature') + setLoadingSpinnerDesc('Preparing document(s) for signing') const createSignature = await signEventForMetaFile( JSON.stringify(content), @@ -634,7 +807,7 @@ export const CreatePage = () => { } // Send notifications to signers and viewers - const sendNotifications = (meta: Meta) => { + const sendNotifications = (notification: SigitNotification) => { // no need to send notification to self so remove it from the list const receivers = ( signers.length > 0 @@ -642,10 +815,15 @@ export const CreatePage = () => { : viewers.map((viewer) => viewer.pubkey) ).filter((receiver) => receiver !== usersPubkey) - return receivers.map((receiver) => sendNotification(receiver, meta)) + return receivers.map((receiver) => sendNotification(receiver, notification)) } - const handleCreate = async () => { + const extractNostrId = (stringifiedEvent: string): string => { + const e = JSON.parse(stringifiedEvent) as SignedEvent + return e.id + } + + const initCreation = async () => { try { if (!validateInputs()) return @@ -657,134 +835,128 @@ export const CreatePage = () => { setLoadingSpinnerDesc('Generating encryption key') const encryptionKey = await generateEncryptionKey() - if (await isOnline()) { - setLoadingSpinnerDesc('generating files.zip') - const arrayBuffer = await generateFilesZip() - if (!arrayBuffer) return + setLoadingSpinnerDesc('Creating marks') + const markConfig = createMarks(fileHashes) - setLoadingSpinnerDesc('Encrypting files.zip') - const encryptedArrayBuffer = await encryptZipFile( - arrayBuffer, - encryptionKey - ) + return { + encryptionKey, + markConfig, + fileHashes + } + } catch (error) { + if (error instanceof Error) { + toast.error(error.message) + } + console.error(error) + setIsLoading(false) + } + } - const markConfig = createMarks(fileHashes) + const handleCreate = async () => { + try { + const result = await initCreation() + if (!result) return - setLoadingSpinnerDesc('Uploading files.zip to file storage') - const fileUrl = await uploadFile(encryptedArrayBuffer) - if (!fileUrl) return + const { encryptionKey, markConfig, fileHashes } = result - setLoadingSpinnerDesc('Generating create signature') - const createSignature = await generateCreateSignature( - markConfig, - fileHashes, - fileUrl - ) - if (!createSignature) return + setLoadingSpinnerDesc('generating files.zip') + const arrayBuffer = await generateFilesZip() + if (!arrayBuffer) return - setLoadingSpinnerDesc('Generating keys for decryption') + setLoadingSpinnerDesc('Encrypting files.zip') + const encryptedArrayBuffer = await encryptZipFile( + arrayBuffer, + encryptionKey + ) - // generate key pairs for decryption - const pubkeys = users.map((user) => user.pubkey) - // also add creator in the list - if (pubkeys.includes(usersPubkey!)) { - pubkeys.push(usersPubkey!) - } + setLoadingSpinnerDesc('Uploading files.zip to file storage') + const fileUrl = await uploadFile(encryptedArrayBuffer) + if (!fileUrl) return - const keys = await generateKeys(pubkeys, encryptionKey) - if (!keys) return + setLoadingSpinnerDesc('Generating create signature') + const createSignature = await generateCreateSignature( + markConfig, + fileHashes, + fileUrl + ) + if (!createSignature) return - const meta: Meta = { - createSignature, - keys, - modifiedAt: unixNow(), - docSignatures: {} - } + setLoadingSpinnerDesc('Generating keys for decryption') - setLoadingSpinnerDesc('Updating user app data') - const event = await updateUsersAppData(meta) - if (!event) return + // generate key pairs for decryption + const pubkeys = users.map((user) => user.pubkey) + // also add creator in the list + if (pubkeys.includes(usersPubkey!)) { + pubkeys.push(usersPubkey!) + } - setLoadingSpinnerDesc('Sending notifications to counterparties') - const promises = sendNotifications(meta) + const keys = await generateKeys(pubkeys, encryptionKey) + if (!keys) return - await Promise.all(promises) - .then(() => { - toast.success('Notifications sent successfully') - }) - .catch(() => { - toast.error('Failed to publish notifications') - }) + setLoadingSpinnerDesc('Generating an open timestamp.') - // Send DM to the next signer - setLoadingSpinnerDesc('Sending DMs') - if (signers.length > 0 && signers[0].pubkey !== usersPubkey) { - // No need to send notification to self so remove it from the list - const nextSigner = signers[0].pubkey + const timestamp = await generateTimestamp(extractNostrId(createSignature)) - if (nextSigner) { - const createSignatureEvent = await parseNostrEvent( - meta.createSignature - ) - const { id } = createSignatureEvent - try { - await sendPrivateDirectMessage( - `Sigit created, visit ${window.location.origin}/#/sign/${id}`, - npubToHex(nextSigner)! - ) - } catch (error) { - if (error instanceof SendDMError) { - toast.error(error.message) - } - console.error(error) - } - } - } + const meta: Meta = { + createSignature, + keys, + modifiedAt: unixNow(), + docSignatures: {} + } - navigate(appPrivateRoutes.sign, { state: { meta } }) - } else { - const zip = new JSZip() + if (timestamp) { + meta.timestamps = [timestamp] + } - selectedFiles.forEach((file) => { - zip.file(`files/${file.name}`, file) + setLoadingSpinnerDesc('Updating user app data') + + const event = await updateUsersAppData([meta]) + if (!event) return + + const metaUrl = await uploadMetaToFileStorage(meta, encryptionKey) + + setLoadingSpinnerDesc('Sending notifications to counterparties') + const promises = sendNotifications({ + metaUrl, + keys: meta.keys + }) + + await Promise.all(promises) + .then(() => { + toast.success('Notifications sent successfully') + }) + .catch(() => { + toast.error('Failed to publish notifications') }) - const markConfig = createMarks(fileHashes) + const isFirstSigner = + signers.length > 0 && signers[0].pubkey === usersPubkey - setLoadingSpinnerDesc('Generating create signature') - const createSignature = await generateCreateSignature( - markConfig, - fileHashes, - '' - ) - if (!createSignature) return - - const meta: Meta = { - createSignature, - modifiedAt: unixNow(), - docSignatures: {} - } - - // add meta to zip + // Don't send notification if creator is next signer + if (signers.length > 0 && !isFirstSigner) { + // Send DM to the next signer + setLoadingSpinnerDesc('Sending DMs') + const nextSigner = signers[0].pubkey + const createSignatureEvent = parseNostrEvent(meta.createSignature) + const { id } = createSignatureEvent try { - const stringifiedMeta = JSON.stringify(meta, null, 2) - zip.file('meta.json', stringifiedMeta) - } catch (err) { - console.error(err) - toast.error('An error occurred in converting meta json to string') - return null + await sendPrivateDirectMessage( + `Sigit created, visit ${window.location.origin}/#/sign/${id}`, + npubToHex(nextSigner)! + ) + } catch (error) { + if (error instanceof SendDMError) { + toast.error(error.message) + } + console.error(error) } + } - const arrayBuffer = await generateZipFile(zip) - if (!arrayBuffer) return - - setLoadingSpinnerDesc('Encrypting zip file') - const encryptedArrayBuffer = await encryptZipFile( - arrayBuffer, - encryptionKey - ) - - await handleOfflineFlow(encryptedArrayBuffer, encryptionKey) + if (isFirstSigner) { + navigate(appPrivateRoutes.sign, { state: { meta } }) + } else { + const createSignatureJson = JSON.parse(createSignature) + navigate(`${appPublicRoutes.verify}/${createSignatureJson.id}`) } } catch (error) { if (error instanceof Error) { @@ -796,9 +968,126 @@ export const CreatePage = () => { } } + const handleCreateOffline = async () => { + try { + const result = await initCreation() + if (!result) return + + const { encryptionKey, markConfig, fileHashes } = result + + const zip = new JSZip() + + selectedFiles.forEach((file) => { + zip.file(`files/${file.name}`, file) + }) + + setLoadingSpinnerDesc('Generating create signature') + const createSignature = await generateCreateSignature( + markConfig, + fileHashes, + '' + ) + if (!createSignature) return + + const meta: Meta = { + createSignature, + modifiedAt: unixNow(), + docSignatures: {} + } + + // add meta to zip + try { + const stringifiedMeta = JSON.stringify(meta, null, 2) + zip.file('meta.json', stringifiedMeta) + } catch (err) { + console.error(err) + toast.error('An error occurred in converting meta json to string') + return null + } + + const arrayBuffer = await generateZipFile(zip) + if (!arrayBuffer) return + + setLoadingSpinnerDesc('Encrypting zip file') + const encryptedArrayBuffer = await encryptZipFile( + arrayBuffer, + encryptionKey + ) + + const finalZipFile = await createFinalZipFile( + encryptedArrayBuffer, + encryptionKey + ) + + if (!finalZipFile) { + setIsLoading(false) + return + } + + // If user is the next signer, we can navigate directly to sign page + const isFirstSigner = signers[0].pubkey === usersPubkey + if (isFirstSigner) { + navigate(appPrivateRoutes.sign, { + state: { arrayBuffer } + }) + } else { + navigate(appPublicRoutes.verify, { + state: { uploadedZip: arrayBuffer } + }) + } + } catch (error) { + if (error instanceof Error) { + toast.error(error.message) + } + console.error(error) + } finally { + setIsLoading(false) + } + } + + /** + * Handles the user search textfield change + * If it's not valid npub or nip05, search will be automatically triggered + */ + const handleSearchAutocompleteTextfieldChange = async ( + e: React.ChangeEvent + ) => { + const value = e.target.value + + const disarmAddOnEnter = () => { + setPastedUserNpubOrNip05(undefined) + } + + // Seems like it's npub format + if (value.startsWith('npub')) { + // We will try to convert npub to hex and if it's successfull that means + // npub is valid + const validHexPubkey = npubToHex(value) + + if (validHexPubkey) { + // Arm the manual user npub add after enter is hit, we don't want to trigger search + setPastedUserNpubOrNip05(value) + } else { + disarmAddOnEnter() + } + } else { + // Disarm the add user on enter hit, and trigger search after 1 second + disarmAddOnEnter() + } + + setUserSearchInput(value) + } + + const parseContent = (event: NostrEvent) => { + try { + return JSON.parse(event.content) + } catch (e) { + return undefined + } + } + return ( <> - {isLoading && } { moveSigner={moveSigner} />
+
- setUserInput(e.target.value)} - onKeyDown={handleInputKeyDown} - error={!!error} + x} + getOptionLabel={(option) => { + let label: string = (option as FoundUser).npub + + const contentJson = parseContent(option as FoundUser) + + if (contentJson?.name) { + label = contentJson.name + } else { + label = option as string + } + + return label + }} + renderOption={(props, option) => { + const { ...optionProps } = props + + const contentJson = parseContent(option) + + return ( + img': { mr: 2, flexShrink: 0 } }} + {...optionProps} + key={option.pubkey} + > + + +
+ {contentJson.name}{' '} + {usersPubkey === option.pubkey ? ( + + Me + + ) : ( + '' + )}{' '} + ({truncate(option.npub, { length: 16 })}) +
+
+ ) + }} + renderInput={(params) => ( + + )} />
- - + {!pastedUserNpubOrNip05 ? ( + + ) : ( + + )}
@@ -934,6 +1291,11 @@ export const CreatePage = () => { Publish + + + Create and export locally + + {!!error && ( {error} )} @@ -943,19 +1305,17 @@ export const CreatePage = () => { centerIcon={faFile} rightIcon={faToolbox} > - {parsingPdf ? ( - - ) : ( - - )} + + {parsingPdf && } + {isLoading && } ) } diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 1a29021..abd3b4e 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -1,10 +1,9 @@ import { Button, TextField } from '@mui/material' -import JSZip from 'jszip' import { useCallback, useEffect, useState } from 'react' import { useNavigate, useSearchParams } from 'react-router-dom' import { toast } from 'react-toastify' import { useAppSelector } from '../../hooks' -import { appPrivateRoutes, appPublicRoutes } from '../../routes' +import { appPrivateRoutes } from '../../routes' import { Meta } from '../../types' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faSearch } from '@fortawesome/free-solid-svg-icons' @@ -15,6 +14,7 @@ import { Container } from '../../components/Container' import styles from './style.module.scss' import { extractSigitCardDisplayInfo, + navigateFromZip, SigitCardDisplayInfo, SigitStatus } from '../../utils' @@ -56,14 +56,15 @@ export const HomePage = () => { [key: string]: SigitCardDisplayInfo }>({}) const usersAppData = useAppSelector((state) => state.userAppData) + const usersPubkey = useAppSelector((state) => state.auth.usersPubkey) useEffect(() => { - if (usersAppData) { + if (usersAppData?.sigits) { const getSigitInfo = async () => { const parsedSigits: { [key: string]: SigitCardDisplayInfo } = {} for (const key in usersAppData.sigits) { if (Object.prototype.hasOwnProperty.call(usersAppData.sigits, key)) { - const sigitInfo = await extractSigitCardDisplayInfo( + const sigitInfo = extractSigitCardDisplayInfo( usersAppData.sigits[key] ) if (sigitInfo) { @@ -80,7 +81,7 @@ export const HomePage = () => { setSigits(usersAppData.sigits) getSigitInfo() } - }, [usersAppData]) + }, [usersAppData?.sigits]) const onDrop = useCallback( async (acceptedFiles: File[]) => { @@ -92,27 +93,12 @@ export const HomePage = () => { const fileName = file.name const fileExtension = fileName.slice(-10) // ".sigit.zip" has 10 characters if (fileExtension === '.sigit.zip') { - const zip = await JSZip.loadAsync(file).catch((err) => { - console.log('err in loading zip file :>> ', err) - toast.error(err.message || 'An error occurred in loading zip file.') - return null - }) + const nav = await navigateFromZip( + file, + usersPubkey as `npub1${string}` + ) - if (!zip) return - - // navigate to sign page if zip contains keys.json - if ('keys.json' in zip.files) { - return navigate(appPrivateRoutes.sign, { - state: { uploadedZip: file } - }) - } - - // navigate to verify page if zip contains meta.json - if ('meta.json' in zip.files) { - return navigate(appPublicRoutes.verify, { - state: { uploadedZip: file } - }) - } + if (nav) return navigate(nav.to, nav.options) toast.error('Invalid SiGit zip file') return @@ -124,7 +110,7 @@ export const HomePage = () => { state: { uploadedFiles: acceptedFiles } }) }, - [navigate] + [navigate, usersPubkey] ) const { getRootProps, getInputProps, isDragActive, open } = useDropzone({ @@ -135,6 +121,46 @@ export const HomePage = () => { const [filter, setFilter] = useState('Show all') const [sort, setSort] = useState('desc') + const renderSubmissions = () => { + const submissions = Object.keys(parsedSigits) + .filter((s) => { + const { title, signedStatus } = parsedSigits[s] + const isMatch = title?.toLowerCase().includes(q.toLowerCase()) + switch (filter) { + case 'Completed': + return signedStatus === SigitStatus.Complete && isMatch + case 'In-progress': + return signedStatus === SigitStatus.Partial && isMatch + case 'Show all': + return isMatch + default: + console.error('Filter case not handled.') + } + }) + .sort((a, b) => { + const x = parsedSigits[a].createdAt ?? 0 + const y = parsedSigits[b].createdAt ?? 0 + return sort === 'desc' ? y - x : x - y + }) + + if (submissions.length) { + return submissions.map((key) => ( + + )) + } else { + return ( +
+

No results

+
+ ) + } + } + return (
@@ -233,36 +259,8 @@ export const HomePage = () => { )} -
- {Object.keys(parsedSigits) - .filter((s) => { - const { title, signedStatus } = parsedSigits[s] - const isMatch = title?.toLowerCase().includes(q.toLowerCase()) - switch (filter) { - case 'Completed': - return signedStatus === SigitStatus.Complete && isMatch - case 'In-progress': - return signedStatus === SigitStatus.Partial && isMatch - case 'Show all': - return isMatch - default: - console.error('Filter case not handled.') - } - }) - .sort((a, b) => { - const x = parsedSigits[a].createdAt ?? 0 - const y = parsedSigits[b].createdAt ?? 0 - return sort === 'desc' ? y - x : x - y - }) - .map((key) => ( - - ))} -
+ +
{renderSubmissions()}
diff --git a/src/pages/home/style.module.scss b/src/pages/home/style.module.scss index 63917a0..5efd4fd 100644 --- a/src/pages/home/style.module.scss +++ b/src/pages/home/style.module.scss @@ -99,3 +99,10 @@ gap: 25px; grid-template-columns: repeat(auto-fit, minmax(365px, 1fr)); } + +.noResults { + display: flex; + justify-content: center; + font-weight: normal; + color: #a1a1a1; +} diff --git a/src/pages/landing/index.tsx b/src/pages/landing/index.tsx index 03738e8..773b923 100644 --- a/src/pages/landing/index.tsx +++ b/src/pages/landing/index.tsx @@ -69,8 +69,8 @@ export const LandingPage = () => { title: <>Verifiable, description: ( <> - Thanks to Schnorr Signatures and Web of Trust, SIGit is far more - auditable than traditional server-based offerings. + SIGit Agreements can be directly verified - unlike traditional, + server-based offerings. ) }, @@ -84,8 +84,8 @@ export const LandingPage = () => { title: <>Works Offline, description: ( <> - Presuming you have a hardware signing device, it is possible to - complete a SIGit round without an internet connection. + It is possible to complete a SIGit round without an internet + connection. ) }, @@ -94,8 +94,8 @@ export const LandingPage = () => { title: <>Multi-Party Signing, description: ( <> - Choose any number of Signers and Viewers, track the signature status, - send reminders, get notifications on completion. + Choose any number of Signers and Viewers, track status, get + notifications on completion. ) } diff --git a/src/pages/nostr/index.tsx b/src/pages/nostr/index.tsx index aa5f11c..738223a 100644 --- a/src/pages/nostr/index.tsx +++ b/src/pages/nostr/index.tsx @@ -1,27 +1,28 @@ -import { launch as launchNostrLoginDialog } from 'nostr-login' +import { useEffect, useState } from 'react' +import { useNavigate, useSearchParams } from 'react-router-dom' import { Button, Divider, TextField } from '@mui/material' -import { getPublicKey, nip19 } from 'nostr-tools' -import { useEffect, useState } from 'react' -import { useAppDispatch } from '../../hooks/store' -import { useNavigate, useSearchParams } from 'react-router-dom' import { toast } from 'react-toastify' + +import { hexToBytes } from '@noble/hashes/utils' +import { launch as launchNostrLoginDialog } from 'nostr-login' +import { getPublicKey, nip19 } from 'nostr-tools' + import { LoadingSpinner } from '../../components/LoadingSpinner' -import { AuthController } from '../../controllers' +import { useAppDispatch, useAuth } from '../../hooks' import { updateKeyPair, updateLoginMethod } from '../../store/actions' import { LoginMethod } from '../../store/auth/types' -import { hexToBytes } from '@noble/hashes/utils' +import { KeyboardCode } from '../../types' import styles from './styles.module.scss' export const Nostr = () => { const [searchParams] = useSearchParams() + const { authAndGetMetadataAndRelaysMap } = useAuth() const dispatch = useAppDispatch() const navigate = useNavigate() - const authController = new AuthController() - const [isLoading, setIsLoading] = useState(false) const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('') const [inputValue, setInputValue] = useState('') @@ -52,7 +53,10 @@ export const Nostr = () => { * Call login function when enter is pressed */ const handleInputKeyDown = (event: React.KeyboardEvent) => { - if (event.code === 'Enter' || event.code === 'NumpadEnter') { + if ( + event.code === KeyboardCode.Enter || + event.code === KeyboardCode.NumpadEnter + ) { event.preventDefault() login() } @@ -98,12 +102,12 @@ export const Nostr = () => { setIsLoading(true) setLoadingSpinnerDesc('Authenticating and finding metadata') - const redirectPath = await authController - .authAndGetMetadataAndRelaysMap(publickey) - .catch((err) => { + const redirectPath = await authAndGetMetadataAndRelaysMap(publickey).catch( + (err) => { toast.error('Error occurred in authentication: ' + err) return null - }) + } + ) if (redirectPath) navigateAfterLogin(redirectPath) diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 7a2f720..8e1e8c0 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -1,48 +1,49 @@ +import { useEffect, useState } from 'react' +import { Link, useNavigate, useParams } from 'react-router-dom' +import { toast } from 'react-toastify' + import ContentCopyIcon from '@mui/icons-material/ContentCopy' import EditIcon from '@mui/icons-material/Edit' import { Box, IconButton, SxProps, Theme, Typography } from '@mui/material' -import { Event, VerifiedEvent, kinds, nip19 } from 'nostr-tools' -import { useEffect, useMemo, useState } from 'react' -import { useAppSelector } from '../../hooks/store' -import { Link, useNavigate, useParams } from 'react-router-dom' -import { toast } from 'react-toastify' + +import { nip19 } from 'nostr-tools' + +import { Container } from '../../components/Container' +import { Footer } from '../../components/Footer/Footer' import { LoadingSpinner } from '../../components/LoadingSpinner' -import { MetadataController } from '../../controllers' +import { useAppSelector } from '../../hooks/store' + import { getProfileSettingsRoute } from '../../routes' -import { NostrJoiningBlock, ProfileMetadata } from '../../types' + import { - getNostrJoiningBlockNumber, getProfileUsername, getRoboHashPicture, hexToNpub, shorten } from '../../utils' + +import { NDKUserProfile } from '@nostr-dev-kit/ndk' +import { useNDKContext } from '../../hooks' import styles from './style.module.scss' -import { Container } from '../../components/Container' -import { Footer } from '../../components/Footer/Footer' export const ProfilePage = () => { const navigate = useNavigate() const { npub } = useParams() - - const metadataController = useMemo(() => MetadataController.getInstance(), []) + const { ndk, findMetadata } = useNDKContext() const [pubkey, setPubkey] = useState() - const [nostrJoiningBlock, setNostrJoiningBlock] = - useState(null) - const [profileMetadata, setProfileMetadata] = useState() - const metadataState = useAppSelector((state) => state.metadata) + const [userProfile, setUserProfile] = useState(null) + + const userRobotImage = useAppSelector((state) => state.user.robotImage) + const currentUserProfile = useAppSelector((state) => state.user.profile) const { usersPubkey } = useAppSelector((state) => state.auth) - const userRobotImage = useAppSelector((state) => state.userRobotImage) const [isUsersOwnProfile, setIsUsersOwnProfile] = useState(false) const [isLoading, setIsLoading] = useState(true) const [loadingSpinnerDesc] = useState('Fetching metadata') - const profileName = pubkey && getProfileUsername(pubkey, profileMetadata) - useEffect(() => { if (npub) { try { @@ -57,60 +58,26 @@ export const ProfilePage = () => { }, [npub, usersPubkey]) useEffect(() => { - if (pubkey) { - getNostrJoiningBlockNumber(pubkey) - .then((res) => { - setNostrJoiningBlock(res) - }) - .catch((err) => { - // todo: handle error - console.log('err :>> ', err) - }) - } - - if (isUsersOwnProfile && metadataState) { - const metadataContent = metadataController.extractProfileMetadataContent( - metadataState as VerifiedEvent - ) - if (metadataContent) { - setProfileMetadata(metadataContent) - setIsLoading(false) - } + if (isUsersOwnProfile && currentUserProfile) { + setUserProfile(currentUserProfile) + setIsLoading(false) return } if (pubkey) { - const getMetadata = async (pubkey: string) => { - const handleMetadataEvent = (event: Event) => { - const metadataContent = - metadataController.extractProfileMetadataContent(event) - if (metadataContent) { - setProfileMetadata(metadataContent) - } - } - - metadataController.on(pubkey, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(event) - } + findMetadata(pubkey) + .then((profile) => { + setUserProfile(profile) + }) + .catch((err) => { + toast.error(err) + }) + .finally(() => { + setIsLoading(false) }) - - const metadataEvent = await metadataController - .findMetadata(pubkey) - .catch((err) => { - toast.error(err) - return null - }) - - if (metadataEvent) handleMetadataEvent(metadataEvent) - - setIsLoading(false) - } - - getMetadata(pubkey) } - }, [isUsersOwnProfile, metadataState, pubkey, metadataController]) + }, [ndk, isUsersOwnProfile, currentUserProfile, pubkey, findMetadata]) /** * Rendering text with button which copies the provided text @@ -146,29 +113,32 @@ export const ProfilePage = () => { * * @returns robohash image url */ - const getProfileImage = (metadata: ProfileMetadata) => { - if (!metadata) return '' + const getProfileImage = (profile: NDKUserProfile | null) => { + if (!profile) return getRoboHashPicture(npub) if (!isUsersOwnProfile) { - return metadata.picture || getRoboHashPicture(npub!) + return profile.image || getRoboHashPicture(npub!) } // userRobotImage is used only when visiting own profile // while kind 0 picture is not set - return metadata.picture || userRobotImage || getRoboHashPicture(npub!) + return profile.image || userRobotImage || getRoboHashPicture(npub!) } + const profileName = + pubkey && getProfileUsername(pubkey, userProfile || undefined) + return ( <> {isLoading && } {pubkey && ( - {profileMetadata && profileMetadata.banner ? ( + {userProfile && userProfile.banner ? ( {`banner ) : ( @@ -189,24 +159,12 @@ export const ProfilePage = () => { > {profileName}
- - - {nostrJoiningBlock - ? `On nostr since ${nostrJoiningBlock.block.toLocaleString()}` - : 'On nostr since: unknown'} - - + {isUsersOwnProfile && ( { display: 'flex' }} > - {profileMetadata && ( - - {profileName} - - )} + + {profileName} + {textElementWithCopyIcon( @@ -242,42 +198,34 @@ export const ProfilePage = () => { )} - {profileMetadata?.nip05 && - textElementWithCopyIcon( - profileMetadata.nip05, - undefined, - 15 - )} + {userProfile?.nip05 && + textElementWithCopyIcon(userProfile.nip05, undefined, 15)} - {profileMetadata?.lud16 && - textElementWithCopyIcon( - profileMetadata.lud16, - undefined, - 15 - )} + {userProfile?.lud16 && + textElementWithCopyIcon(userProfile.lud16, undefined, 15)} - {profileMetadata?.website && ( + {userProfile?.website && ( - {profileMetadata.website} + {userProfile.website} )} - {profileMetadata?.about && ( + {userProfile?.about && ( - {profileMetadata.about} + {userProfile.about} )} diff --git a/src/pages/settings/profile/index.tsx b/src/pages/settings/profile/index.tsx index 1a3e34f..57383a7 100644 --- a/src/pages/settings/profile/index.tsx +++ b/src/pages/settings/profile/index.tsx @@ -1,4 +1,11 @@ +import React, { useEffect, useRef, useState } from 'react' +import { useParams } from 'react-router-dom' +import { toast } from 'react-toastify' + +import { SmartToy } from '@mui/icons-material' import ContentCopyIcon from '@mui/icons-material/ContentCopy' +import LaunchIcon from '@mui/icons-material/Launch' +import { LoadingButton } from '@mui/lab' import { Box, IconButton, @@ -7,59 +14,48 @@ import { ListItem, ListSubheader, TextField, - Tooltip, - Typography, - useTheme + Tooltip } from '@mui/material' -import { UnsignedEvent, nip19, kinds, VerifiedEvent, Event } from 'nostr-tools' -import React, { useEffect, useRef, useState } from 'react' -import { Link, useParams } from 'react-router-dom' -import { toast } from 'react-toastify' -import { MetadataController, NostrController } from '../../../controllers' -import { NostrJoiningBlock, ProfileMetadata } from '../../../types' -import styles from './style.module.scss' + +import { NDKEvent, NDKUserProfile, serializeProfile } from '@nostr-dev-kit/ndk' +import { launch as launchNostrLoginDialog } from 'nostr-login' +import { kinds, nip19, UnsignedEvent } from 'nostr-tools' + +import { NostrController } from '../../../controllers' + +import { useNDKContext } from '../../../hooks' import { useAppDispatch, useAppSelector } from '../../../hooks/store' -import { LoadingButton } from '@mui/lab' -import { Dispatch } from '../../../store/store' -import { setMetadataEvent } from '../../../store/actions' -import { LoadingSpinner } from '../../../components/LoadingSpinner' -import { LoginMethod, NostrLoginAuthMethod } from '../../../store/auth/types' -import { SmartToy } from '@mui/icons-material' -import { - getNostrJoiningBlockNumber, - getRoboHashPicture, - unixNow -} from '../../../utils' +import { getRoboHashPicture, unixNow } from '../../../utils' + import { Container } from '../../../components/Container' import { Footer } from '../../../components/Footer/Footer' -import LaunchIcon from '@mui/icons-material/Launch' -import { launch as launchNostrLoginDialog } from 'nostr-login' +import { LoadingSpinner } from '../../../components/LoadingSpinner' + +import { setUserProfile as updateUserProfile } from '../../../store/actions' +import { LoginMethod, NostrLoginAuthMethod } from '../../../store/auth/types' +import { Dispatch } from '../../../store/store' + +import styles from './style.module.scss' export const ProfileSettingsPage = () => { - const theme = useTheme() - - const { npub } = useParams() - const dispatch: Dispatch = useAppDispatch() - const metadataController = MetadataController.getInstance() - const nostrController = NostrController.getInstance() + const { npub } = useParams() + const { ndk, findMetadata, publish } = useNDKContext() const [pubkey, setPubkey] = useState() - const [nostrJoiningBlock, setNostrJoiningBlock] = - useState(null) - const [profileMetadata, setProfileMetadata] = useState() - const [savingProfileMetadata, setSavingProfileMetadata] = useState(false) - const metadataState = useAppSelector((state) => state.metadata) + const [userProfile, setUserProfile] = useState(null) + + const userRobotImage = useAppSelector((state) => state.user.robotImage) + const currentUserProfile = useAppSelector((state) => state.user.profile) const keys = useAppSelector((state) => state.auth?.keyPair) const { usersPubkey, loginMethod, nostrLoginAuthMethod } = useAppSelector( (state) => state.auth ) - const userRobotImage = useAppSelector((state) => state.userRobotImage) + const [savingProfileMetadata, setSavingProfileMetadata] = useState(false) const [isUsersOwnProfile, setIsUsersOwnProfile] = useState(false) - const [isLoading, setIsLoading] = useState(true) const [loadingSpinnerDesc] = useState('Fetching metadata') @@ -79,63 +75,30 @@ export const ProfileSettingsPage = () => { }, [npub, usersPubkey]) useEffect(() => { - if (pubkey) { - getNostrJoiningBlockNumber(pubkey) - .then((res) => { - setNostrJoiningBlock(res) - }) - .catch((err) => { - // todo: handle error - console.log('err :>> ', err) - }) - } + if (isUsersOwnProfile && currentUserProfile) { + setUserProfile(currentUserProfile) - if (isUsersOwnProfile && metadataState) { - const metadataContent = metadataController.extractProfileMetadataContent( - metadataState as VerifiedEvent - ) - if (metadataContent) { - setProfileMetadata(metadataContent) - setIsLoading(false) - } + setIsLoading(false) return } if (pubkey) { - const getMetadata = async (pubkey: string) => { - const handleMetadataEvent = (event: Event) => { - const metadataContent = - metadataController.extractProfileMetadataContent(event) - if (metadataContent) { - setProfileMetadata(metadataContent) - } - } - - metadataController.on(pubkey, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(event) - } + findMetadata(pubkey) + .then((profile) => { + setUserProfile(profile) + }) + .catch((err) => { + toast.error(err) + }) + .finally(() => { + setIsLoading(false) }) - - const metadataEvent = await metadataController - .findMetadata(pubkey) - .catch((err) => { - toast.error(err) - return null - }) - - if (metadataEvent) handleMetadataEvent(metadataEvent) - - setIsLoading(false) - } - - getMetadata(pubkey) } - }, [isUsersOwnProfile, metadataState, pubkey, metadataController]) + }, [ndk, isUsersOwnProfile, currentUserProfile, pubkey, findMetadata]) const editItem = ( - key: keyof ProfileMetadata, + key: keyof NDKUserProfile, label: string, multiline = false, rows = 1, @@ -145,7 +108,7 @@ export const ProfileSettingsPage = () => { { onChange={(event: React.ChangeEvent) => { const { value } = event.target - setProfileMetadata((prev) => ({ + setUserProfile((prev) => ({ ...prev, [key]: value })) @@ -197,34 +160,47 @@ export const ProfileSettingsPage = () => { ) const handleSaveMetadata = async () => { + if (!userProfile) return + setSavingProfileMetadata(true) - const content = JSON.stringify(profileMetadata) + const serializedProfile = serializeProfile(userProfile) - // We need to omit cachedAt and create new event - // Relay will reject if created_at is too late - const updatedMetadataState: UnsignedEvent = { - content: content, + const unsignedEvent: UnsignedEvent = { + content: serializedProfile, created_at: unixNow(), kind: kinds.Metadata, pubkey: pubkey!, - tags: metadataState?.tags || [] + tags: [] } + const nostrController = NostrController.getInstance() const signedEvent = await nostrController - .signEvent(updatedMetadataState) + .signEvent(unsignedEvent) .catch((error) => { toast.error(`Error saving profile metadata. ${error}`) + return null }) - if (signedEvent) { - if (!metadataController.validate(signedEvent)) { - toast.error(`Metadata is not valid.`) - } + if (!signedEvent) { + setSavingProfileMetadata(false) + return + } - await metadataController.publishMetadataEvent(signedEvent) + const ndkEvent = new NDKEvent(ndk, signedEvent) + const publishedOnRelays = await publish(ndkEvent) - dispatch(setMetadataEvent(signedEvent)) + // Handle cases where publishing failed or succeeded + if (publishedOnRelays.length === 0) { + toast.error('Failed to publish event on any relay') + } else { + toast.success( + `Event published successfully to the following relays\n\n${publishedOnRelays.join( + '\n' + )}` + ) + + dispatch(updateUserProfile(userProfile)) } setSavingProfileMetadata(false) @@ -241,7 +217,7 @@ export const ProfileSettingsPage = () => { const robotAvatarLink = getRoboHashPicture(npub!, robotSet.current) - setProfileMetadata((prev) => ({ + setUserProfile((prev) => ({ ...prev, picture: robotAvatarLink })) @@ -267,14 +243,14 @@ export const ProfileSettingsPage = () => { * * @returns robohash image url */ - const getProfileImage = (metadata: ProfileMetadata) => { + const getProfileImage = (profile: NDKUserProfile) => { if (!isUsersOwnProfile) { - return metadata.picture || getRoboHashPicture(npub!) + return profile.image || getRoboHashPicture(npub!) } // userRobotImage is used only when visiting own profile // while kind 0 picture is not set - return metadata.picture || userRobotImage || getRoboHashPicture(npub!) + return profile.image || userRobotImage || getRoboHashPicture(npub!) } return ( @@ -300,7 +276,7 @@ export const ProfileSettingsPage = () => { } > - {profileMetadata && ( + {userProfile && (
{ flexDirection: 'column' }} > - {profileMetadata.banner ? ( + {userProfile.banner ? ( Banner Image ) : ( @@ -334,32 +310,17 @@ export const ProfileSettingsPage = () => { event.currentTarget.src = getRoboHashPicture(npub!) }} className={styles.img} - src={getProfileImage(profileMetadata)} + src={getProfileImage(userProfile)} alt="Profile Image" /> - - {nostrJoiningBlock && ( - - On nostr since {nostrJoiningBlock.block.toLocaleString()} - - )} - {editItem('picture', 'Picture URL', undefined, undefined, { + {editItem('image', 'Picture URL', undefined, undefined, { endAdornment: isUsersOwnProfile ? robohashButton() : undefined })} {editItem('name', 'Username')} - {editItem('display_name', 'Display Name')} + {editItem('displayName', 'Display Name')} {editItem('nip05', 'Nostr Address (nip05)')} {editItem('lud16', 'Lightning Address (lud16)')} {editItem('about', 'About', true, 4)} @@ -368,6 +329,7 @@ export const ProfileSettingsPage = () => { <> {usersPubkey && copyItem(nip19.npubEncode(usersPubkey), 'Public Key')} + {loginMethod === LoginMethod.privateKey && keys && keys.private && diff --git a/src/pages/settings/relays/index.tsx b/src/pages/settings/relays/index.tsx index a1f5223..c0542c5 100644 --- a/src/pages/settings/relays/index.tsx +++ b/src/pages/settings/relays/index.tsx @@ -13,26 +13,40 @@ import Switch from '@mui/material/Switch' import { useEffect, useState } from 'react' import { toast } from 'react-toastify' import { Container } from '../../../components/Container' -import { relayController } from '../../../controllers' -import { useAppDispatch, useAppSelector, useDidMount } from '../../../hooks' +import { + useAppDispatch, + useAppSelector, + useDidMount, + useDvm, + useNDKContext +} from '../../../hooks' import { setRelayMapAction } from '../../../store/actions' import { RelayConnectionState, RelayFee, RelayInfo } from '../../../types' import { capitalizeFirstLetter, compareObjects, - getRelayInfo, - getRelayMap, + getRelayMapFromNDKRelayList, hexToNpub, publishRelayMap, - shorten + shorten, + timeout } from '../../../utils' import styles from './style.module.scss' import { Footer } from '../../../components/Footer/Footer' +import { + getRelayListForUser, + NDKRelayList, + NDKRelayStatus +} from '@nostr-dev-kit/ndk' export const RelaysPage = () => { + const dispatch = useAppDispatch() + const { ndk, publish } = useNDKContext() + const { getRelayInfo } = useDvm() + const usersPubkey = useAppSelector((state) => state.auth?.usersPubkey) - const dispatch = useAppDispatch() + const [ndkRelayList, setNDKRelayList] = useState(null) const [newRelayURI, setNewRelayURI] = useState() const [newRelayURIerror, setNewRelayURIerror] = useState() @@ -40,24 +54,56 @@ export const RelaysPage = () => { const relayMap = useAppSelector((state) => state.relays?.map) const relaysInfo = useAppSelector((state) => state.relays?.info) - const webSocketPrefix = 'wss://' + const webSocketPrefix = + newRelayURI?.startsWith('wss://') || newRelayURI?.startsWith('ws://') + ? '' + : 'wss://' - useDidMount(() => { + // fetch relay list from relays + useEffect(() => { if (usersPubkey) { - getRelayMap(usersPubkey).then((newRelayMap) => { - if (!compareObjects(relayMap, newRelayMap.map)) { - dispatch(setRelayMapAction(newRelayMap.map)) - } - }) + Promise.race([getRelayListForUser(usersPubkey, ndk), timeout(10000)]) + .then((res) => { + setNDKRelayList(res) + }) + .catch((err) => { + toast.error( + `An error occurred in fetching user relay list: ${ + err.message || err + }` + ) + setNDKRelayList(new NDKRelayList(ndk)) + }) } - }) + }, [usersPubkey, ndk]) + + // construct the RelayMap from newly received NDKRelayList event + // and compare it with existing relay map in redux store + // if there are any differences then update the redux store with + // new relay map + useEffect(() => { + if (ndkRelayList) { + const newRelayMap = getRelayMapFromNDKRelayList(ndkRelayList) + + if (!compareObjects(relayMap, newRelayMap)) { + dispatch(setRelayMapAction(newRelayMap)) + } + } + + // we want to run this effect only when ndkRelayList is changed + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ndkRelayList]) useEffect(() => { + if (!relayMap) return + // Display notification if an empty relay map has been received - if (relayMap && Object.keys(relayMap).length === 0) { + if (Object.keys(relayMap).length === 0) { relayRequirementWarning() + } else { + getRelayInfo(Object.keys(relayMap)) } - }, [relayMap]) + }, [relayMap, getRelayInfo]) const relayRequirementWarning = () => toast.warning('At least one write relay is needed for SIGit to work.') @@ -85,7 +131,8 @@ export const RelaysPage = () => { const relayMapPublishingRes = await publishRelayMap( relayMapCopy, usersPubkey, - [relay] + ndk, + publish ).catch((err) => handlePublishRelayMapError(err)) if (relayMapPublishingRes) { @@ -132,7 +179,9 @@ export const RelaysPage = () => { // Publish updated relay map const relayMapPublishingRes = await publishRelayMap( relayMapCopy, - usersPubkey + usersPubkey, + ndk, + publish ).catch((err) => handlePublishRelayMapError(err)) if (relayMapPublishingRes) { @@ -151,7 +200,7 @@ export const RelaysPage = () => { // Check if new relay URI is a valid string if ( relayURI && - !/^wss:\/\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}/.test( + !/^wss?:\/\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}/.test( relayURI ) ) { @@ -161,9 +210,10 @@ export const RelaysPage = () => { ) } } else if (relayURI && usersPubkey) { - const relay = await relayController.connectRelay(relayURI) + const ndkRelay = ndk.pool.getRelay(relayURI) + await ndkRelay.connect(5000) - if (relay && relay.connected) { + if (ndkRelay.status >= NDKRelayStatus.CONNECTED) { const relayMapCopy = JSON.parse(JSON.stringify(relayMap)) relayMapCopy[relayURI] = { write: true, read: true } @@ -171,7 +221,9 @@ export const RelaysPage = () => { // Publish updated relay map const relayMapPublishingRes = await publishRelayMap( relayMapCopy, - usersPubkey + usersPubkey, + ndk, + publish ).catch((err) => handlePublishRelayMapError(err)) if (relayMapPublishingRes) { @@ -211,7 +263,13 @@ export const RelaysPage = () => { }} className={styles.relayURItextfield} /> - @@ -256,19 +314,36 @@ const RelayItem = ({ handleLeaveRelay, handleRelayWriteChange }: RelayItemProp) => { + const { ndk } = useNDKContext() + const [relayConnectionStatus, setRelayConnectionStatus] = useState() const [displayRelayInfo, setDisplayRelayInfo] = useState(false) useDidMount(() => { - relayController.connectRelay(relayURI).then((relay) => { - if (relay && relay.connected) { + const ndkPool = ndk.pool + + ndkPool.on('relay:connect', (relay) => { + if (relay.url === relayURI) { setRelayConnectionStatus(RelayConnectionState.Connected) - } else { + } + }) + + ndkPool.on('relay:disconnect', (relay) => { + if (relay.url === relayURI) { setRelayConnectionStatus(RelayConnectionState.NotConnected) } }) + + const relay = ndkPool.getRelay(relayURI) + if (relay) { + setRelayConnectionStatus( + relay.status >= NDKRelayStatus.CONNECTED + ? RelayConnectionState.Connected + : RelayConnectionState.NotConnected + ) + } }) return ( diff --git a/src/pages/settings/relays/style.module.scss b/src/pages/settings/relays/style.module.scss index a5654c5..3db7760 100644 --- a/src/pages/settings/relays/style.module.scss +++ b/src/pages/settings/relays/style.module.scss @@ -12,6 +12,7 @@ flex-direction: row; gap: 10px; width: 100%; + align-items: start; } .sectionIcon { diff --git a/src/pages/sign/index.tsx b/src/pages/sign/index.tsx index ed925e1..309ee1f 100644 --- a/src/pages/sign/index.tsx +++ b/src/pages/sign/index.tsx @@ -1,12 +1,9 @@ -import { Box, Button, Typography } from '@mui/material' import axios from 'axios' -import saveAs from 'file-saver' import JSZip from 'jszip' import _ from 'lodash' -import { MuiFileInput } from 'mui-file-input' import { Event, verifyEvent } from 'nostr-tools' -import { useCallback, useEffect, useState } from 'react' -import { useAppSelector } from '../../hooks/store' +import { useEffect, useMemo, useState } from 'react' +import { useAppSelector } from '../../hooks' import { useLocation, useNavigate, useParams } from 'react-router-dom' import { toast } from 'react-toastify' import { LoadingSpinner } from '../../components/LoadingSpinner' @@ -15,102 +12,77 @@ import { appPublicRoutes } from '../../routes' import { CreateSignatureEventContent, Meta, SignedEvent } from '../../types' import { decryptArrayBuffer, - encryptArrayBuffer, extractMarksFromSignedMeta, extractZipUrlAndEncryptionKey, - generateEncryptionKey, - generateKeysFile, + filterMarksByPubkey, + findOtherUserMarks, getCurrentUserFiles, + getCurrentUserMarks, getHash, hexToNpub, - isOnline, loadZip, - unixNow, npubToHex, parseJson, + encryptAndUploadMarks, readContentOfZipEntry, - sendNotification, signEventForMetaFile, - updateUsersAppData, - findOtherUserMarks, - timeout, + unixNow, + updateMarks, + uploadMetaToFileStorage, sendPrivateDirectMessage, parseNostrEvent } from '../../utils' -import { Container } from '../../components/Container' -import { DisplayMeta } from './internal/displayMeta' -import styles from './style.module.scss' import { CurrentUserMark, Mark } from '../../types/mark.ts' -import { getLastSignersSig, isFullySigned } from '../../utils/sign.ts' -import { - filterMarksByPubkey, - getCurrentUserMarks, - isCurrentUserMarksComplete, - updateMarks -} from '../../utils' import PdfMarking from '../../components/PDFView/PdfMarking.tsx' -import { - convertToSigitFile, - getZipWithFiles, - SigitFile -} from '../../utils/file.ts' -import { ARRAY_BUFFER, DEFLATE } from '../../utils/const.ts' +import { convertToSigitFile, SigitFile } from '../../utils/file.ts' +import { generateTimestamp } from '../../utils/opentimestamps.ts' +import { MARK_TYPE_CONFIG } from '../../components/MarkTypeStrategy/MarkStrategy.tsx' +import { useNDK } from '../../hooks/useNDK.ts' import { SendDMError } from '../../types/errors/SendDMError.ts' -enum SignedStatus { - Fully_Signed, - User_Is_Next_Signer, - User_Is_Not_Next_Signer -} - export const SignPage = () => { const navigate = useNavigate() const location = useLocation() const params = useParams() + const { updateUsersAppData, sendNotification } = useNDK() const usersAppData = useAppSelector((state) => state.userAppData) /** - * Received from `location.state` - * - * uploadedZip will be received from home page when a user uploads a sigit zip wrapper that contains keys.json - * arrayBuffer (decryptedArrayBuffer) will be received in navigation from create page in offline mode - * meta (metaInNavState) will be received in navigation from create & home page in online mode + * In the online mode, Sigit ID can be obtained either from the router state + * using location or from UsersAppData */ - let metaInNavState = location?.state?.meta || undefined - const { arrayBuffer: decryptedArrayBuffer, uploadedZip } = location.state || { - decryptedArrayBuffer: undefined, - uploadedZip: undefined - } + const metaInNavState = useMemo(() => { + if (usersAppData) { + const sigitCreateId = params.id - /** - * If userAppData (redux) is available, and we have the route param (sigit id) - * which is actually a `createEventId`, we will fetch a `sigit` - * based on the provided route ID and set fetched `sigit` to the `metaInNavState` - */ - if (usersAppData) { - const sigitCreateId = params.id + if (sigitCreateId) { + const sigit = usersAppData.sigits[sigitCreateId] - if (sigitCreateId) { - const sigit = usersAppData.sigits[sigitCreateId] - - if (sigit) { - metaInNavState = sigit + if (sigit) { + return sigit + } } } + + return location?.state?.meta || undefined + }, [location, usersAppData, params.id]) + + /** + * Received from `location.state` + * + * arrayBuffer (decryptedArrayBuffer) will be received in navigation from create page in offline mode + */ + const { arrayBuffer: decryptedArrayBuffer, uploadedZip } = location.state || { + decryptedArrayBuffer: undefined } - const [displayInput, setDisplayInput] = useState(false) - - const [selectedFile, setSelectedFile] = useState(null) - const [files, setFiles] = useState<{ [filename: string]: SigitFile }>({}) const [isLoading, setIsLoading] = useState(true) const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('') const [meta, setMeta] = useState(null) - const [signedStatus, setSignedStatus] = useState() const [submittedBy, setSubmittedBy] = useState() @@ -124,66 +96,14 @@ export const SignPage = () => { [key: string]: string | null }>({}) - const [signedBy, setSignedBy] = useState<`npub1${string}`[]>([]) - - const [nextSinger, setNextSinger] = useState() - - // This state variable indicates whether the logged-in user is a signer, a creator, or neither. - const [isSignerOrCreator, setIsSignerOrCreator] = useState(false) - const usersPubkey = useAppSelector((state) => state.auth.usersPubkey) const nostrController = NostrController.getInstance() const [currentUserMarks, setCurrentUserMarks] = useState( [] ) - const [isMarksCompleted, setIsMarksCompleted] = useState(false) const [otherUserMarks, setOtherUserMarks] = useState([]) - useEffect(() => { - if (signers.length > 0) { - // check if all signers have signed then its fully signed - if (isFullySigned(signers, signedBy)) { - setSignedStatus(SignedStatus.Fully_Signed) - } else { - for (const signer of signers) { - if (!signedBy.includes(signer)) { - // signers in meta.json are in npub1 format - // so, convert it to hex before setting to nextSigner - setNextSinger(npubToHex(signer)!) - - const usersNpub = hexToNpub(usersPubkey!) - - if (signer === usersNpub) { - // logged in user is the next signer - setSignedStatus(SignedStatus.User_Is_Next_Signer) - } else { - setSignedStatus(SignedStatus.User_Is_Not_Next_Signer) - } - - break - } - } - } - } else { - // there's no signer just viewers. So its fully signed - setSignedStatus(SignedStatus.Fully_Signed) - } - - // Determine and set the status of the user - if (submittedBy && usersPubkey && submittedBy === usersPubkey) { - // If the submission was made by the user, set the status to true - setIsSignerOrCreator(true) - } else if (usersPubkey) { - // Convert the user's public key from hex to npub format - const usersNpub = hexToNpub(usersPubkey) - if (signers.includes(usersNpub)) { - // If the user's npub is in the list of signers, set the status to true - setIsSignerOrCreator(true) - } - } - }, [signers, signedBy, usersPubkey, submittedBy]) - useEffect(() => { const handleUpdatedMeta = async (meta: Meta) => { const createSignatureEvent = await parseJson( @@ -239,101 +159,54 @@ export const SignPage = () => { const signedMarks = extractMarksFromSignedMeta(meta) const currentUserMarks = getCurrentUserMarks(metaMarks, signedMarks) const otherUserMarks = findOtherUserMarks(signedMarks, usersPubkey!) + + if (meta.keys) { + for (let i = 0; i < otherUserMarks.length; i++) { + const m = otherUserMarks[i] + const { sender, keys } = meta.keys + const usersNpub = hexToNpub(usersPubkey) + if (usersNpub in keys) { + const encryptionKey = await nostrController + .nip04Decrypt(sender, keys[usersNpub]) + .catch((err) => { + console.log( + 'An error occurred in decrypting encryption key', + err + ) + return null + }) + + try { + const { fetchAndDecrypt } = MARK_TYPE_CONFIG[m.type] || {} + if ( + typeof fetchAndDecrypt === 'function' && + m.value && + encryptionKey + ) { + otherUserMarks[i].value = await fetchAndDecrypt( + m.value, + encryptionKey + ) + } + } catch (error) { + console.error(`Error during mark fetchAndDecrypt phase`, error) + } + } + } + } + setOtherUserMarks(otherUserMarks) setCurrentUserMarks(currentUserMarks) - setIsMarksCompleted(isCurrentUserMarksComplete(currentUserMarks)) } - - setSignedBy(Object.keys(meta.docSignatures) as `npub1${string}`[]) } if (meta) { handleUpdatedMeta(meta) } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [meta, usersPubkey]) - const handleDownload = async () => { - if (Object.entries(files).length === 0 || !meta || !usersPubkey) return - setLoadingSpinnerDesc('Generating file') - try { - const zip = await getZipWithFiles(meta, files) - const arrayBuffer = await zip.generateAsync({ - type: ARRAY_BUFFER, - compression: DEFLATE, - compressionOptions: { - level: 6 - } - }) - if (!arrayBuffer) return - const blob = new Blob([arrayBuffer]) - saveAs(blob, `exported-${unixNow()}.sigit.zip`) - } catch (error) { - console.log('error in zip:>> ', error) - if (error instanceof Error) { - toast.error(error.message || 'Error occurred in generating zip file') - } - } - } - - const decrypt = useCallback( - async (file: File) => { - setLoadingSpinnerDesc('Decrypting file') - - const zip = await loadZip(file) - if (!zip) return - - const parsedKeysJson = await parseKeysJson(zip) - if (!parsedKeysJson) return - - const encryptedArrayBuffer = await readContentOfZipEntry( - zip, - 'compressed.sigit', - 'arraybuffer' - ) - - if (!encryptedArrayBuffer) return - - const { keys, sender } = parsedKeysJson - - for (const key of keys) { - // decrypt the encryptionKey, with timeout (duration = 60 seconds) - const encryptionKey = await Promise.race([ - nostrController.nip04Decrypt(sender, key), - timeout(60000) - ]) - .then((res) => { - return res - }) - .catch((err) => { - console.log('err :>> ', err) - return null - }) - - // Return if encryption failed - if (!encryptionKey) continue - - const arrayBuffer = await decryptArrayBuffer( - encryptedArrayBuffer, - encryptionKey - ) - .catch((err) => { - console.log('err in decryption:>> ', err) - return null - }) - .finally(() => { - setIsLoading(false) - }) - - if (arrayBuffer) return arrayBuffer - } - - return null - }, - [nostrController] - ) - useEffect(() => { - // online mode - from create and home page views if (metaInNavState) { const processSigit = async () => { setIsLoading(true) @@ -368,27 +241,20 @@ export const SignPage = () => { } processSigit() - } else if (decryptedArrayBuffer) { - handleDecryptedArrayBuffer(decryptedArrayBuffer).finally(() => - setIsLoading(false) + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + useEffect(() => { + if (decryptedArrayBuffer || uploadedZip) { + handleDecryptedArrayBuffer(decryptedArrayBuffer || uploadedZip).finally( + () => setIsLoading(false) ) - } else if (uploadedZip) { - decrypt(uploadedZip) - .then((arrayBuffer) => { - if (arrayBuffer) handleDecryptedArrayBuffer(arrayBuffer) - }) - .catch((err) => { - console.error(`error occurred in decryption`, err) - toast.error(err.message || `error occurred in decryption`) - }) - .finally(() => { - setIsLoading(false) - }) } else { setIsLoading(false) - setDisplayInput(true) } - }, [decryptedArrayBuffer, uploadedZip, metaInNavState, decrypt]) + }, [decryptedArrayBuffer, uploadedZip]) const handleArrayBufferFromBlossom = async ( arrayBuffer: ArrayBuffer, @@ -447,30 +313,12 @@ export const SignPage = () => { setMarks(updatedMarks) } - const parseKeysJson = async (zip: JSZip) => { - const keysFileContent = await readContentOfZipEntry( - zip, - 'keys.json', - 'string' - ) - - if (!keysFileContent) return null - - return await parseJson<{ sender: string; keys: string[] }>( - keysFileContent - ).catch((err) => { - console.log(`Error parsing content of keys.json:`, err) - toast.error(err.message || `Error parsing content of keys.json`) - return null - }) - } - - const handleDecryptedArrayBuffer = async (arrayBuffer: ArrayBuffer) => { - const decryptedZipFile = new File([arrayBuffer], 'decrypted.zip') - + const handleDecryptedArrayBuffer = async ( + decryptedArrayBuffer: ArrayBuffer + ) => { setLoadingSpinnerDesc('Parsing zip file') - const zip = await loadZip(decryptedZipFile) + const zip = await loadZip(decryptedArrayBuffer) if (!zip) return const files: { [filename: string]: SigitFile } = {} @@ -503,9 +351,6 @@ export const SignPage = () => { setFiles(files) setCurrentFileHashes(fileHashes) - - setDisplayInput(false) - setLoadingSpinnerDesc('Parsing meta.json') const metaFileContent = await readContentOfZipEntry( @@ -533,46 +378,130 @@ export const SignPage = () => { setMeta(parsedMetaJson) } - const handleDecrypt = async () => { - if (!selectedFile) return - - setIsLoading(true) - const arrayBuffer = await decrypt(selectedFile) - - if (!arrayBuffer) return - - handleDecryptedArrayBuffer(arrayBuffer) - } - - const handleSign = async () => { + const initializeSigning = async (type: 'online' | 'offline') => { if (Object.entries(files).length === 0 || !meta) return setIsLoading(true) - setLoadingSpinnerDesc('Signing nostr event') - const prevSig = getPrevSignersSig(hexToNpub(usersPubkey!)) + const usersNpub = hexToNpub(usersPubkey!) + const prevSig = getPrevSignersSig(usersNpub) if (!prevSig) { - setIsLoading(false) toast.error('Previous signature is invalid') return } const marks = getSignerMarksForMeta() || [] - const signedEvent = await signEventForMeta({ prevSig, marks }) + let encryptionKey: string | undefined + if (meta.keys) { + const { sender, keys } = meta.keys + encryptionKey = await nostrController + .nip04Decrypt(sender, keys[usersNpub]) + .catch((err) => { + // Log and display an error message if decryption fails + console.log('An error occurred in decrypting encryption key', err) + toast.error('An error occurred in decrypting encryption key') + return undefined + }) + } + + const processedMarks = + type === 'online' + ? await encryptAndUploadMarks(marks, encryptionKey) + : marks + + const signedEvent = await signEventForMeta({ + prevSig, + marks: processedMarks + }) + if (!signedEvent) return const updatedMeta = updateMetaSignatures(meta, signedEvent) - if (await isOnline()) { - await handleOnlineFlow(updatedMeta) - } else { - setMeta(updatedMeta) - setIsLoading(false) + return { + encryptionKey, + updatedMeta, + signedEvent } } + const handleSign = async () => { + const result = await initializeSigning('online') + if (!result) { + setIsLoading(false) + return + } + + const { encryptionKey, updatedMeta, signedEvent } = result + + setLoadingSpinnerDesc('Generating an open timestamp.') + + const timestamp = await generateTimestamp(signedEvent.id) + if (timestamp) { + updatedMeta.timestamps = [...(updatedMeta.timestamps || []), timestamp] + updatedMeta.modifiedAt = unixNow() + } + + await handleOnlineFlow(updatedMeta, encryptionKey) + + const createSignature = JSON.parse(updatedMeta.createSignature) + navigate(`${appPublicRoutes.verify}/${createSignature.id}`) + } + + const handleSignOffline = async () => { + const result = await initializeSigning('offline') + if (!result) { + setIsLoading(false) + return + } + + const { updatedMeta } = result + + const zip = new JSZip() + for (const [filename, value] of Object.entries(files)) { + zip.file(`files/${filename}`, await value.arrayBuffer()) + } + const stringifiedMeta = JSON.stringify(updatedMeta, null, 2) + zip.file('meta.json', stringifiedMeta) + + // Handle errors during zip file generation + const handleZipError = (err: unknown) => { + console.log('Error in zip:>> ', err) + setIsLoading(false) + if (err instanceof Error) { + toast.error(err.message || 'Error occurred in generating zip file') + } + return null + } + + setLoadingSpinnerDesc('Generating zip file') + + const arrayBuffer = await zip + .generateAsync({ + type: 'arraybuffer', + compression: 'DEFLATE', + compressionOptions: { level: 6 } + }) + .catch(handleZipError) + + if (!arrayBuffer) { + setIsLoading(false) + return + } + + // Create a File object with the Blob data + const blob = new Blob([arrayBuffer]) + const file = new File([blob], `request-${unixNow()}.sigit.zip`, { + type: 'application/zip' + }) + + setIsLoading(false) + + navigate(`${appPublicRoutes.verify}`, { state: { uploadedZip: file } }) + } + // Sign the event for the meta file const signEventForMeta = async (signerContent: { prevSig: string @@ -601,85 +530,38 @@ export const SignPage = () => { return metaCopy } - // create final zip file - const createFinalZipFile = async ( - encryptedArrayBuffer: ArrayBuffer, - encryptionKey: string - ): Promise => { - // Get the current timestamp in seconds - const blob = new Blob([encryptedArrayBuffer]) - // Create a File object with the Blob data - const file = new File([blob], `compressed.sigit`, { - type: 'application/sigit' - }) - - const isLastSigner = checkIsLastSigner(signers) - - const userSet = new Set() - - if (isLastSigner) { - if (submittedBy) { - userSet.add(submittedBy) - } - - signers.forEach((signer) => { - userSet.add(npubToHex(signer)!) - }) - - viewers.forEach((viewer) => { - userSet.add(npubToHex(viewer)!) - }) - } else { - const usersNpub = hexToNpub(usersPubkey!) - const signerIndex = signers.indexOf(usersNpub) - const nextSigner = signers[signerIndex + 1] - userSet.add(npubToHex(nextSigner)!) - } - - const keysFileContent = await generateKeysFile( - Array.from(userSet), - encryptionKey - ) - if (!keysFileContent) return null - - const zip = new JSZip() - zip.file(`compressed.sigit`, file) - zip.file('keys.json', keysFileContent) - - const arraybuffer = await zip - .generateAsync({ - type: 'arraybuffer', - compression: 'DEFLATE', - compressionOptions: { level: 6 } - }) - .catch(handleZipError) - - if (!arraybuffer) return null - - return new File([new Blob([arraybuffer])], `${unixNow()}.sigit.zip`, { - type: 'application/zip' - }) - } - - // Handle errors during zip file generation - const handleZipError = (err: unknown) => { - console.log('Error in zip:>> ', err) - setIsLoading(false) - if (err instanceof Error) { - toast.error(err.message || 'Error occurred in generating zip file') - } - return null + // Check if the current user is the last signer + const checkIsLastSigner = (signers: string[]): boolean => { + const usersNpub = hexToNpub(usersPubkey!) + const lastSignerIndex = signers.length - 1 + const signerIndex = signers.indexOf(usersNpub) + return signerIndex === lastSignerIndex } // Handle the online flow: update users app data and send notifications - const handleOnlineFlow = async (meta: Meta) => { + const handleOnlineFlow = async ( + meta: Meta, + encryptionKey: string | undefined + ) => { setLoadingSpinnerDesc('Updating users app data') - const updatedEvent = await updateUsersAppData(meta) + const updatedEvent = await updateUsersAppData([meta]) if (!updatedEvent) { setIsLoading(false) return } + let metaUrl: string + try { + metaUrl = await uploadMetaToFileStorage(meta, encryptionKey) + } catch (error) { + if (error instanceof Error) { + toast.error(error.message) + } + console.error(error) + setIsLoading(false) + return + } + const userSet = new Set<`npub1${string}`>() if (submittedBy && submittedBy !== usersPubkey) { userSet.add(hexToNpub(submittedBy)) @@ -712,7 +594,7 @@ export const SignPage = () => { setLoadingSpinnerDesc('Sending notifications') const users = Array.from(userSet) const promises = users.map((user) => - sendNotification(npubToHex(user)!, meta) + sendNotification(npubToHex(user)!, { metaUrl, keys: meta.keys }) ) await Promise.all(promises) .then(() => { @@ -785,128 +667,6 @@ export const SignPage = () => { setIsLoading(false) } - // Check if the current user is the last signer - const checkIsLastSigner = (signers: string[]): boolean => { - const usersNpub = hexToNpub(usersPubkey!) - const lastSignerIndex = signers.length - 1 - const signerIndex = signers.indexOf(usersNpub) - return signerIndex === lastSignerIndex - } - - const handleExport = async () => { - if (Object.entries(files).length === 0 || !meta || !usersPubkey) return - - const usersNpub = hexToNpub(usersPubkey) - if ( - !signers.includes(usersNpub) && - !viewers.includes(usersNpub) && - submittedBy !== usersNpub - ) - return - - setIsLoading(true) - setLoadingSpinnerDesc('Signing nostr event') - - if (!meta) return - - const prevSig = getLastSignersSig(meta, signers) - if (!prevSig) return - - const signedEvent = await signEventForMetaFile( - JSON.stringify({ - prevSig - }), - nostrController, - setIsLoading - ) - - if (!signedEvent) return - - const exportSignature = JSON.stringify(signedEvent, null, 2) - - const stringifiedMeta = JSON.stringify( - { - ...meta, - exportSignature - }, - null, - 2 - ) - - const zip = new JSZip() - - zip.file('meta.json', stringifiedMeta) - - for (const [fileName, file] of Object.entries(files)) { - zip.file(`files/${fileName}`, await file.arrayBuffer()) - } - - const arrayBuffer = await zip - .generateAsync({ - type: 'arraybuffer', - compression: 'DEFLATE', - compressionOptions: { - level: 6 - } - }) - .catch((err) => { - console.log('err in zip:>> ', err) - setIsLoading(false) - toast.error(err.message || 'Error occurred in generating zip file') - return null - }) - - if (!arrayBuffer) return - - const blob = new Blob([arrayBuffer]) - saveAs(blob, `exported-${unixNow()}.sigit.zip`) - - setIsLoading(false) - - navigate(appPublicRoutes.verify) - } - - const handleEncryptedExport = async () => { - if (Object.entries(files).length === 0 || !meta) return - - const zip = new JSZip() - - const stringifiedMeta = JSON.stringify(meta, null, 2) - - zip.file('meta.json', stringifiedMeta) - - for (const [fileName, file] of Object.entries(files)) { - zip.file(`files/${fileName}`, await file.arrayBuffer()) - } - - const arrayBuffer = await zip - .generateAsync({ - type: 'arraybuffer', - compression: 'DEFLATE', - compressionOptions: { - level: 6 - } - }) - .catch((err) => { - console.log('err in zip:>> ', err) - setIsLoading(false) - toast.error(err.message || 'Error occurred in generating zip file') - return null - }) - - if (!arrayBuffer) return - - const key = await generateEncryptionKey() - - setLoadingSpinnerDesc('Encrypting zip file') - const encryptedArrayBuffer = await encryptArrayBuffer(arrayBuffer, key) - - const finalZipFile = await createFinalZipFile(encryptedArrayBuffer, key) - - if (!finalZipFile) return - saveAs(finalZipFile, `exported-${unixNow()}.sigit.zip`) - } - /** * This function accepts an npub of a signer and return the signature of its previous signer. * This prevSig will be used in the content of the provided signer's signedEvent @@ -944,90 +704,16 @@ export const SignPage = () => { return } - if (!isMarksCompleted && signedStatus === SignedStatus.User_Is_Next_Signer) { - return ( - - ) - } - return ( - <> - - {displayInput && ( - <> - - Select sigit file - - - - setSelectedFile(value)} - /> - - - {selectedFile && ( - - - - )} - - )} - - {submittedBy && Object.entries(files).length > 0 && meta && ( - <> - - - {signedStatus === SignedStatus.Fully_Signed && ( - - - - )} - - {signedStatus === SignedStatus.User_Is_Next_Signer && ( - - - - )} - - {isSignerOrCreator && ( - - - - )} - - )} - - + ) } diff --git a/src/pages/sign/internal/displayMeta.tsx b/src/pages/sign/internal/displayMeta.tsx index 9335495..1da3b93 100644 --- a/src/pages/sign/internal/displayMeta.tsx +++ b/src/pages/sign/internal/displayMeta.tsx @@ -1,10 +1,12 @@ +import { useEffect, useState } from 'react' +import { toast } from 'react-toastify' + import { - Meta, - ProfileMetadata, - SignedEventContent, - User, - UserRole -} from '../../../types' + Cancel, + CheckCircle, + Download, + HourglassTop +} from '@mui/icons-material' import { Box, IconButton, @@ -20,22 +22,19 @@ import { Typography, useTheme } from '@mui/material' -import { - Download, - CheckCircle, - Cancel, - HourglassTop -} from '@mui/icons-material' + import saveAs from 'file-saver' -import { kinds, Event } from 'nostr-tools' -import { useState, useEffect } from 'react' -import { toast } from 'react-toastify' + +import { Event } from 'nostr-tools' + import { UserAvatar } from '../../../components/UserAvatar' -import { MetadataController } from '../../../controllers' -import { npubToHex, hexToNpub, parseJson } from '../../../utils' -import styles from '../style.module.scss' + +import { Meta, SignedEventContent, User, UserRole } from '../../../types' +import { hexToNpub, npubToHex, parseJson } from '../../../utils' import { SigitFile } from '../../../utils/file' +import styles from '../style.module.scss' + type DisplayMetaProps = { meta: Meta files: { [fileName: string]: SigitFile } @@ -67,9 +66,6 @@ export const DisplayMeta = ({ theme.palette.background.paper ) - const [metadata, setMetadata] = useState<{ [key: string]: ProfileMetadata }>( - {} - ) const [users, setUsers] = useState([]) useEffect(() => { @@ -104,45 +100,6 @@ export const DisplayMeta = ({ }) }, [signers, viewers]) - useEffect(() => { - const metadataController = MetadataController.getInstance() - - const hexKeys: string[] = [ - npubToHex(submittedBy)!, - ...users.map((user) => user.pubkey) - ] - - hexKeys.forEach((key) => { - if (!(key in metadata)) { - const handleMetadataEvent = (event: Event) => { - const metadataContent = - metadataController.extractProfileMetadataContent(event) - - if (metadataContent) - setMetadata((prev) => ({ - ...prev, - [key]: metadataContent - })) - } - - metadataController.on(key, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(event) - } - }) - - metadataController - .findMetadata(key) - .then((metadataEvent) => { - if (metadataEvent) handleMetadataEvent(metadataEvent) - }) - .catch((err) => { - console.error(`error occurred in finding metadata for: ${key}`, err) - }) - } - }) - }, [users, submittedBy, metadata]) - const downloadFile = async (fileName: string) => { const file = files[fileName] saveAs(file) @@ -229,7 +186,6 @@ export const DisplayMeta = ({ key={user.pubkey} meta={meta} user={user} - metadata={metadata} signedBy={signedBy} nextSigner={nextSigner} getPrevSignersSig={getPrevSignersSig} @@ -258,7 +214,6 @@ enum UserStatus { type DisplayUserProps = { meta: Meta user: User - metadata: { [key: string]: ProfileMetadata } signedBy: `npub1${string}`[] nextSigner?: string getPrevSignersSig: (usersNpub: string) => string | null diff --git a/src/pages/verify/index.tsx b/src/pages/verify/index.tsx index 000341e..d80671d 100644 --- a/src/pages/verify/index.tsx +++ b/src/pages/verify/index.tsx @@ -1,11 +1,17 @@ import { Box, Button, Typography } from '@mui/material' import JSZip from 'jszip' import { MuiFileInput } from 'mui-file-input' -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { toast } from 'react-toastify' import { LoadingSpinner } from '../../components/LoadingSpinner' import { NostrController } from '../../controllers' -import { DocSignatureEvent, Meta } from '../../types' +import { + DocSignatureEvent, + Meta, + SignedEvent, + OpenTimestamp, + OpenTimestampUpgradeVerifyResponse +} from '../../types' import { decryptArrayBuffer, getHash, @@ -14,19 +20,26 @@ import { parseJson, readContentOfZipEntry, signEventForMetaFile, - getCurrentUserFiles + getCurrentUserFiles, + npubToHex, + generateEncryptionKey, + encryptArrayBuffer, + generateKeysFile, + ARRAY_BUFFER, + DEFLATE, + uploadMetaToFileStorage, + decrypt } from '../../utils' import styles from './style.module.scss' -import { useLocation } from 'react-router-dom' +import { useLocation, useParams } from 'react-router-dom' import axios from 'axios' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' -import { useAppSelector } from '../../hooks/store' -import { getLastSignersSig } from '../../utils/sign.ts' +import { useAppSelector, useNDK } from '../../hooks' import { saveAs } from 'file-saver' import { Container } from '../../components/Container' import { useSigitMeta } from '../../hooks/useSigitMeta.tsx' import { StickySideColumns } from '../../layouts/StickySideColumns.tsx' -import { UsersDetails } from '../../components/UsersDetails.tsx/index.tsx' +import { UsersDetails } from '../../components/UsersDetails.tsx' import FileList from '../../components/FileList' import { CurrentUserFile } from '../../types/file.ts' import { Mark } from '../../types/mark.ts' @@ -44,6 +57,10 @@ import { faFile, faFileDownload } from '@fortawesome/free-solid-svg-icons' +import { upgradeAndVerifyTimestamp } from '../../utils/opentimestamps.ts' +import _ from 'lodash' +import { MarkRender } from '../../components/MarkTypeStrategy/MarkRender.tsx' +import { SignerService } from '../../services/index.ts' interface PdfViewProps { files: CurrentUserFile[] @@ -89,7 +106,10 @@ const SlimPdfView = ({ const m = parsedSignatureEvents[ e as `npub1${string}` ].parsedContent?.marks.filter( - (m) => m.pdfFileHash == hash && m.location.page == i + (m) => + (m.pdfFileHash + ? m.pdfFileHash == hash + : m.fileHash == hash) && m.location.page == i ) if (m) { marks.push(...m) @@ -118,7 +138,11 @@ const SlimPdfView = ({ fontSize: inPx(from(page.width, FONT_SIZE)) }} > - {m.value} +
) })} @@ -149,6 +173,10 @@ const SlimPdfView = ({ export const VerifyPage = () => { const location = useLocation() + const params = useParams() + const { updateUsersAppData, sendNotification } = useNDK() + + const usersAppData = useAppSelector((state) => state.userAppData) const usersPubkey = useAppSelector((state) => state.auth.usersPubkey) const nostrController = NostrController.getInstance() @@ -160,15 +188,29 @@ export const VerifyPage = () => { * uploadedZip will be received from home page when a user uploads a sigit zip wrapper that contains meta.json * meta will be received in navigation from create & home page in online mode */ - const { uploadedZip, meta: metaInNavState } = location.state || {} + let metaInNavState = location?.state?.meta || undefined + const uploadedZip = location?.state?.uploadedZip || undefined const [selectedFile, setSelectedFile] = useState(null) - useEffect(() => { - if (uploadedZip) { - setSelectedFile(uploadedZip) + + /** + * If `userAppData` is present it means user is logged in and we can extract list of `sigits` from the store. + * If ID is present in the URL we search in the `sigits` list + * Otherwise sigit is set from the `location.state.meta` + */ + if (usersAppData) { + const sigitCreateId = params.id + + if (sigitCreateId) { + const sigit = usersAppData.sigits[sigitCreateId] + + if (sigit) { + metaInNavState = sigit + } } - }, [uploadedZip]) + } const [meta, setMeta] = useState(metaInNavState) + const { submittedBy, zipUrl, @@ -176,7 +218,8 @@ export const VerifyPage = () => { signers, viewers, fileHashes, - parsedSignatureEvents + parsedSignatureEvents, + timestamps } = useSigitMeta(meta) const [files, setFiles] = useState<{ [filename: string]: SigitFile }>({}) @@ -186,6 +229,16 @@ export const VerifyPage = () => { [key: string]: string | null }>({}) + const signTimestampEvent = async (signerContent: { + timestamps: OpenTimestamp[] + }): Promise => { + return await signEventForMetaFile( + JSON.stringify(signerContent), + nostrController, + setIsLoading + ) + } + useEffect(() => { if (Object.entries(files).length > 0) { const tmp = getCurrentUserFiles(files, currentFileHashes, fileHashes) @@ -193,105 +246,267 @@ export const VerifyPage = () => { } }, [currentFileHashes, fileHashes, files]) + useEffect(() => { + if ( + timestamps && + timestamps.length > 0 && + usersPubkey && + submittedBy && + parsedSignatureEvents + ) { + if (timestamps.every((t) => !!t.verification)) { + return + } + const upgradeT = async (timestamps: OpenTimestamp[]) => { + try { + setLoadingSpinnerDesc('Upgrading your timestamps.') + + const findCreatorTimestamp = (timestamps: OpenTimestamp[]) => { + if (usersPubkey === submittedBy) { + return timestamps[0] + } + } + + const findSignerTimestamp = (timestamps: OpenTimestamp[]) => { + const parsedEvent = parsedSignatureEvents[hexToNpub(usersPubkey)] + if (parsedEvent?.id) { + return timestamps.find((t) => t.nostrId === parsedEvent.id) + } + } + + /** + * Checks if timestamp verification has been achieved for the first time. + * Note that the upgrade flag is separate from verification. It is possible for a timestamp + * to not be upgraded, but to be verified for the first time. + * @param upgradedTimestamp + * @param timestamps + */ + const isNewlyVerified = ( + upgradedTimestamp: OpenTimestampUpgradeVerifyResponse, + timestamps: OpenTimestamp[] + ) => { + if (!upgradedTimestamp.verified) return false + const oldT = timestamps.find( + (t) => t.nostrId === upgradedTimestamp.timestamp.nostrId + ) + if (!oldT) return false + if (!oldT.verification && upgradedTimestamp.verified) return true + } + + const userTimestamps: OpenTimestamp[] = [] + + const creatorTimestamp = findCreatorTimestamp(timestamps) + if (creatorTimestamp) { + userTimestamps.push(creatorTimestamp) + } + + const signerTimestamp = findSignerTimestamp(timestamps) + if (signerTimestamp) { + userTimestamps.push(signerTimestamp) + } + + if (userTimestamps.every((t) => !!t.verification)) { + return + } + + const upgradedUserTimestamps = await Promise.all( + userTimestamps.map(upgradeAndVerifyTimestamp) + ) + + const upgradedTimestamps = upgradedUserTimestamps + .filter((t) => t.upgraded || isNewlyVerified(t, userTimestamps)) + .map((t) => { + const timestamp: OpenTimestamp = { ...t.timestamp } + if (t.verified) { + timestamp.verification = t.verification + } + return timestamp + }) + + if (upgradedTimestamps.length === 0) { + return + } + + setLoadingSpinnerDesc('Signing a timestamp upgrade event.') + + const signedEvent = await signTimestampEvent({ + timestamps: upgradedTimestamps + }) + if (!signedEvent) return + + const finalTimestamps = timestamps.map((t) => { + const upgraded = upgradedTimestamps.find( + (tu) => tu.nostrId === t.nostrId + ) + if (upgraded) { + return { + ...upgraded, + signature: JSON.stringify(signedEvent, null, 2) + } + } + return t + }) + + const updatedMeta = _.cloneDeep(meta) + updatedMeta.timestamps = [...finalTimestamps] + updatedMeta.modifiedAt = unixNow() + + const updatedEvent = await updateUsersAppData([updatedMeta]) + if (!updatedEvent) return + + const metaUrl = await uploadMetaToFileStorage( + updatedMeta, + encryptionKey + ) + + const userSet = new Set<`npub1${string}`>() + signers.forEach((signer) => { + if (signer !== usersPubkey) { + userSet.add(signer) + } + }) + + viewers.forEach((viewer) => { + userSet.add(viewer) + }) + + const users = Array.from(userSet) + const promises = users.map((user) => + sendNotification(npubToHex(user)!, { + metaUrl, + keys: meta.keys! + }) + ) + + await Promise.all(promises) + + toast.success('Timestamp updates have been sent successfully.') + + setMeta(meta) + } catch (err) { + console.error(err) + toast.error( + 'There was an error upgrading or verifying your timestamps!' + ) + } + } + upgradeT(timestamps) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [timestamps, submittedBy, parsedSignatureEvents]) + useEffect(() => { if (metaInNavState && encryptionKey) { const processSigit = async () => { setIsLoading(true) setLoadingSpinnerDesc('Fetching file from file server') - axios - .get(zipUrl, { + try { + const res = await axios.get(zipUrl, { responseType: 'arraybuffer' }) - .then(async (res) => { - const fileName = zipUrl.split('/').pop() - const file = new File([res.data], fileName!) - const encryptedArrayBuffer = await file.arrayBuffer() - const arrayBuffer = await decryptArrayBuffer( - encryptedArrayBuffer, - encryptionKey - ).catch((err) => { - console.log('err in decryption:>> ', err) + const fileName = zipUrl.split('/').pop() + const file = new File([res.data], fileName!) + + const encryptedArrayBuffer = await file.arrayBuffer() + const arrayBuffer = await decryptArrayBuffer( + encryptedArrayBuffer, + encryptionKey + ).catch((err) => { + console.log('err in decryption:>> ', err) + toast.error(err.message || 'An error occurred in decrypting file.') + return null + }) + + if (arrayBuffer) { + const zip = await JSZip.loadAsync(arrayBuffer).catch((err) => { + console.log('err in loading zip file :>> ', err) toast.error( - err.message || 'An error occurred in decrypting file.' + err.message || 'An error occurred in loading zip file.' ) return null }) - if (arrayBuffer) { - const zip = await JSZip.loadAsync(arrayBuffer).catch((err) => { - console.log('err in loading zip file :>> ', err) - toast.error( - err.message || 'An error occurred in loading zip file.' - ) - return null - }) + if (!zip) return - if (!zip) return + const files: { [fileName: string]: SigitFile } = {} + const fileHashes: { [key: string]: string | null } = {} + const fileNames = Object.values(zip.files).map( + (entry) => entry.name + ) - const files: { [fileName: string]: SigitFile } = {} - const fileHashes: { [key: string]: string | null } = {} - const fileNames = Object.values(zip.files).map( - (entry) => entry.name + // generate hashes for all entries in files folder of zipArchive + // these hashes can be used to verify the originality of files + for (const fileName of fileNames) { + const arrayBuffer = await readContentOfZipEntry( + zip, + fileName, + 'arraybuffer' ) - // generate hashes for all entries in files folder of zipArchive - // these hashes can be used to verify the originality of files - for (const fileName of fileNames) { - const arrayBuffer = await readContentOfZipEntry( - zip, - fileName, - 'arraybuffer' + if (arrayBuffer) { + files[fileName] = await convertToSigitFile( + arrayBuffer, + fileName! ) + const hash = await getHash(arrayBuffer) - if (arrayBuffer) { - files[fileName] = await convertToSigitFile( - arrayBuffer, - fileName! - ) - const hash = await getHash(arrayBuffer) - - if (hash) { - fileHashes[fileName.replace(/^files\//, '')] = hash - } - } else { - fileHashes[fileName.replace(/^files\//, '')] = null + if (hash) { + fileHashes[fileName.replace(/^files\//, '')] = hash } + } else { + fileHashes[fileName.replace(/^files\//, '')] = null } - - setCurrentFileHashes(fileHashes) - setFiles(files) - - setIsLoading(false) } - }) - .catch((err) => { - console.error(`error occurred in getting file from ${zipUrl}`, err) - toast.error( - err.message || `error occurred in getting file from ${zipUrl}` - ) - }) - .finally(() => { + + setCurrentFileHashes(fileHashes) + setFiles(files) setIsLoading(false) - }) + } + } catch (err) { + const message = `error occurred in getting file from ${zipUrl}` + console.error(message, err) + if (err instanceof Error) toast.error(err.message) + else toast.error(message) + } finally { + setIsLoading(false) + } } processSigit() } }, [encryptionKey, metaInNavState, zipUrl]) - const handleVerify = async () => { - if (!selectedFile) return + const handleVerify = useCallback(async (selectedFile: File) => { setIsLoading(true) + setLoadingSpinnerDesc('Loading zip file') - const zip = await JSZip.loadAsync(selectedFile).catch((err) => { + let zip = await JSZip.loadAsync(selectedFile).catch((err) => { console.log('err in loading zip file :>> ', err) toast.error(err.message || 'An error occurred in loading zip file.') return null }) - if (!zip) return + if (!zip) { + return setIsLoading(false) + } + + if ('keys.json' in zip.files) { + // Decrypt + setLoadingSpinnerDesc('Decrypting zip file content') + const arrayBuffer = await decrypt(selectedFile).catch((err) => { + console.error(`error occurred in decryption`, err) + toast.error(err.message || `error occurred in decryption`) + }) + + if (arrayBuffer) { + // Replace the zip and continue processing + zip = await JSZip.loadAsync(arrayBuffer) + } + } + + setLoadingSpinnerDesc('Opening zip file content') const files: { [filename: string]: SigitFile } = {} const fileHashes: { [key: string]: string | null } = {} @@ -348,15 +563,120 @@ export const VerifyPage = () => { } ) - if (!parsedMetaJson) return + if (!parsedMetaJson) { + setIsLoading(false) + return + } setMeta(parsedMetaJson) setIsLoading(false) + }, []) + + useEffect(() => { + if (uploadedZip) { + handleVerify(uploadedZip) + } + }, [handleVerify, uploadedZip]) + + // Handle errors during zip file generation + const handleZipError = (err: unknown) => { + console.log('Error in zip:>> ', err) + setIsLoading(false) + if (err instanceof Error) { + toast.error(err.message || 'Error occurred in generating zip file') + } + return null } - const handleMarkedExport = async () => { - if (Object.entries(files).length === 0 || !meta || !usersPubkey) return + // create final zip file + const createFinalZipFile = async ( + encryptedArrayBuffer: ArrayBuffer, + encryptionKey: string + ): Promise => { + // Get the current timestamp in seconds + const blob = new Blob([encryptedArrayBuffer]) + // Create a File object with the Blob data + const file = new File([blob], `compressed.sigit`, { + type: 'application/sigit' + }) + + const userSet = new Set() + if (submittedBy) { + userSet.add(submittedBy) + } + signers.forEach((signer) => { + userSet.add(npubToHex(signer)!) + }) + viewers.forEach((viewer) => { + userSet.add(npubToHex(viewer)!) + }) + + const keysFileContent = await generateKeysFile( + Array.from(userSet), + encryptionKey + ) + if (!keysFileContent) return null + + const zip = new JSZip() + zip.file(`compressed.sigit`, file) + zip.file('keys.json', keysFileContent) + + const arraybuffer = await zip + .generateAsync({ + type: 'arraybuffer', + compression: 'DEFLATE', + compressionOptions: { level: 6 } + }) + .catch(handleZipError) + + if (!arraybuffer) return null + + return new File([new Blob([arraybuffer])], `${unixNow()}.sigit.zip`, { + type: 'application/zip' + }) + } + + const handleExport = async () => { + const arrayBuffer = await prepareZipExport() + if (!arrayBuffer) { + setIsLoading(false) + return + } + + const blob = new Blob([arrayBuffer]) + saveAs(blob, `exported-${unixNow()}.sigit.zip`) + + setIsLoading(false) + } + + const handleEncryptedExport = async () => { + const arrayBuffer = await prepareZipExport() + if (!arrayBuffer) { + setIsLoading(false) + return + } + + const key = await generateEncryptionKey() + + setLoadingSpinnerDesc('Encrypting zip file') + const encryptedArrayBuffer = await encryptArrayBuffer(arrayBuffer, key) + + const finalZipFile = await createFinalZipFile(encryptedArrayBuffer, key) + + if (!finalZipFile) { + setIsLoading(false) + return + } + + saveAs(finalZipFile, `exported-${unixNow()}.sigit.zip`) + + setIsLoading(false) + } + + const prepareZipExport = async (): Promise => { + if (Object.entries(files).length === 0 || !meta || !usersPubkey) + return Promise.resolve(null) const usersNpub = hexToNpub(usersPubkey) if ( @@ -364,14 +684,18 @@ export const VerifyPage = () => { !viewers.includes(usersNpub) && submittedBy !== usersNpub ) { - return + return Promise.resolve(null) } setIsLoading(true) setLoadingSpinnerDesc('Signing nostr event') - const prevSig = getLastSignersSig(meta, signers) - if (!prevSig) return + if (!meta) return Promise.resolve(null) + + const signerService = new SignerService(meta) + const prevSig = signerService.getLastSignerSig() + + if (!prevSig) return Promise.resolve(null) const signedEvent = await signEventForMetaFile( JSON.stringify({ prevSig }), @@ -379,7 +703,7 @@ export const VerifyPage = () => { setIsLoading ) - if (!signedEvent) return + if (!signedEvent) return Promise.resolve(null) const exportSignature = JSON.stringify(signedEvent, null, 2) const updatedMeta = { ...meta, exportSignature } @@ -390,8 +714,8 @@ export const VerifyPage = () => { const arrayBuffer = await zip .generateAsync({ - type: 'arraybuffer', - compression: 'DEFLATE', + type: ARRAY_BUFFER, + compression: DEFLATE, compressionOptions: { level: 6 } @@ -403,12 +727,9 @@ export const VerifyPage = () => { return null }) - if (!arrayBuffer) return + if (!arrayBuffer) return Promise.resolve(null) - const blob = new Blob([arrayBuffer]) - saveAs(blob, `exported-${unixNow()}.sigit.zip`) - - setIsLoading(false) + return Promise.resolve(arrayBuffer) } return ( @@ -434,7 +755,10 @@ export const VerifyPage = () => { {selectedFile && ( - @@ -454,8 +778,8 @@ export const VerifyPage = () => { )} currentFile={currentFile} setCurrentFile={setCurrentFile} - handleDownload={handleMarkedExport} - downloadLabel="Download Sigit" + handleExport={handleExport} + handleEncryptedExport={handleEncryptedExport} /> ) } diff --git a/src/pages/verify/style.module.scss b/src/pages/verify/style.module.scss index b63ba60..a89ea95 100644 --- a/src/pages/verify/style.module.scss +++ b/src/pages/verify/style.module.scss @@ -53,10 +53,6 @@ .mark { position: absolute; - - display: flex; - justify-content: center; - align-items: center; } [data-dev='true'] { diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 97d66c3..f3580f9 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,16 +1,4 @@ -import { CreatePage } from '../pages/create' -import { HomePage } from '../pages/home' -import { LandingPage } from '../pages/landing' -import { ProfilePage } from '../pages/profile' -import { SettingsPage } from '../pages/settings/Settings' -import { CacheSettingsPage } from '../pages/settings/cache' -import { NostrLoginPage } from '../pages/settings/nostrLogin' -import { ProfileSettingsPage } from '../pages/settings/profile' -import { RelaysPage } from '../pages/settings/relays' -import { SignPage } from '../pages/sign' -import { VerifyPage } from '../pages/verify' import { hexToNpub } from '../utils' -import { Route, RouteProps } from 'react-router-dom' export const appPrivateRoutes = { homePage: '/', @@ -39,93 +27,3 @@ export const getProfileRoute = (hexKey: string) => export const getProfileSettingsRoute = (hexKey: string) => appPrivateRoutes.profileSettings.replace(':npub', hexToNpub(hexKey)) - -/** - * Helper type allows for extending react-router-dom's **RouteProps** with generic type - */ -type CustomRouteProps = T & - Omit & { - children?: Array> - } - -/** - * This function maps over nested routes with optional condition for rendering - * @param {CustomRouteProps[]} routes - routes list - * @param {RenderConditionCallbackFn} renderConditionCallbackFn - render condition callback (default true) - */ -export function recursiveRouteRenderer( - routes?: CustomRouteProps[], - renderConditionCallbackFn: (route: CustomRouteProps) => boolean = () => - true -) { - if (!routes) return null - - // Callback allows us to pass arbitrary conditions for each route's rendering - // Skipping the callback will by default evaluate to true (show route) - return routes.map((route, index) => - renderConditionCallbackFn(route) ? ( - - {recursiveRouteRenderer(route.children, renderConditionCallbackFn)} - - ) : null - ) -} - -type PublicRouteProps = CustomRouteProps<{ - hiddenWhenLoggedIn?: boolean -}> - -export const publicRoutes: PublicRouteProps[] = [ - { - path: appPublicRoutes.landingPage, - hiddenWhenLoggedIn: true, - element: - }, - { - path: appPublicRoutes.profile, - element: - }, - { - path: appPublicRoutes.verify, - element: - } -] - -export const privateRoutes = [ - { - path: appPrivateRoutes.homePage, - element: - }, - { - path: appPrivateRoutes.create, - element: - }, - { - path: `${appPrivateRoutes.sign}/:id?`, - element: - }, - { - path: appPrivateRoutes.settings, - element: - }, - { - path: appPrivateRoutes.profileSettings, - element: - }, - { - path: appPrivateRoutes.cacheSettings, - element: - }, - { - path: appPrivateRoutes.relays, - element: - }, - { - path: appPrivateRoutes.nostrLogin, - element: - } -] diff --git a/src/routes/util.tsx b/src/routes/util.tsx new file mode 100644 index 0000000..8773b81 --- /dev/null +++ b/src/routes/util.tsx @@ -0,0 +1,103 @@ +import { Route, RouteProps } from 'react-router-dom' +import { appPrivateRoutes, appPublicRoutes } from '.' +import { CreatePage } from '../pages/create' +import { HomePage } from '../pages/home' +import { LandingPage } from '../pages/landing' +import { ProfilePage } from '../pages/profile' +import { CacheSettingsPage } from '../pages/settings/cache' +import { NostrLoginPage } from '../pages/settings/nostrLogin' +import { ProfileSettingsPage } from '../pages/settings/profile' +import { RelaysPage } from '../pages/settings/relays' +import { SettingsPage } from '../pages/settings/Settings' +import { SignPage } from '../pages/sign' +import { VerifyPage } from '../pages/verify' + +/** + * Helper type allows for extending react-router-dom's **RouteProps** with generic type + */ +type CustomRouteProps = T & + Omit & { + children?: Array> + } + +/** + * This function maps over nested routes with optional condition for rendering + * @param {CustomRouteProps[]} routes - routes list + * @param {RenderConditionCallbackFn} renderConditionCallbackFn - render condition callback (default true) + */ +export function recursiveRouteRenderer( + routes?: CustomRouteProps[], + renderConditionCallbackFn: (route: CustomRouteProps) => boolean = () => + true +) { + if (!routes) return null + + // Callback allows us to pass arbitrary conditions for each route's rendering + // Skipping the callback will by default evaluate to true (show route) + return routes.map((route, index) => + renderConditionCallbackFn(route) ? ( + + {recursiveRouteRenderer(route.children, renderConditionCallbackFn)} + + ) : null + ) +} + +type PublicRouteProps = CustomRouteProps<{ + hiddenWhenLoggedIn?: boolean +}> + +export const publicRoutes: PublicRouteProps[] = [ + { + path: appPublicRoutes.landingPage, + hiddenWhenLoggedIn: true, + element: + }, + { + path: appPublicRoutes.profile, + element: + }, + { + path: `${appPublicRoutes.verify}/:id?`, + element: + } +] + +export const privateRoutes = [ + { + path: appPrivateRoutes.homePage, + element: + }, + { + path: appPrivateRoutes.create, + element: + }, + { + path: `${appPrivateRoutes.sign}/:id?`, + element: + }, + { + path: appPrivateRoutes.settings, + element: + }, + { + path: appPrivateRoutes.profileSettings, + element: + }, + { + path: appPrivateRoutes.cacheSettings, + element: + }, + { + path: appPrivateRoutes.relays, + element: + }, + { + path: appPrivateRoutes.nostrLogin, + element: + } +] diff --git a/src/services/index.ts b/src/services/index.ts index 79b5128..b8d275a 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1 +1,2 @@ export * from './cache' +export * from './signer' diff --git a/src/services/signer/index.ts b/src/services/signer/index.ts new file mode 100644 index 0000000..8851028 --- /dev/null +++ b/src/services/signer/index.ts @@ -0,0 +1,143 @@ +import { toast } from 'react-toastify' +import { Meta, SignedEventContent } from '../../types' +import { + parseCreateSignatureEventContent, + parseNostrEvent, + SigitStatus, + SignStatus +} from '../../utils' +import { MetaParseError } from '../../types/errors/MetaParseError' +import { verifyEvent } from 'nostr-tools' +import { appPrivateRoutes, appPublicRoutes } from '../../routes' + +export class SignerService { + #signers: `npub1${string}`[] = [] + #nextSigner: `npub1${string}` | undefined + #signatures = new Map<`npub1${string}`, string>() + #signersStatus = new Map<`npub1${string}`, SignStatus>() + #lastSignerSig: string | undefined + constructor(source: Meta) { + this.#process(source.createSignature, source.docSignatures) + } + + getNextSigner = () => { + return this.#nextSigner + } + + isNextSigner = (npub: `npub1${string}`) => { + return this.#nextSigner === npub + } + + isLastSigner = (npub: `npub1${string}`) => { + const lastIndex = this.#signers.length - 1 + const npubIndex = this.#signers.indexOf(npub) + return npubIndex === lastIndex + } + + #isFullySigned = () => { + const signedBy = Object.keys(this.#signatures) as `npub1${string}`[] + const isCompletelySigned = this.#signers.every((signer) => + signedBy.includes(signer) + ) + return isCompletelySigned + } + + getSignedStatus = () => { + return this.#isFullySigned() ? SigitStatus.Complete : SigitStatus.Partial + } + + getSignerStatus = (npub: `npub1${string}`) => { + return this.#signersStatus.get(npub) + } + + getNavigate = (npub: `npub1${string}`) => { + return this.isNextSigner(npub) + ? appPrivateRoutes.sign + : appPublicRoutes.verify + } + + getLastSignerSig = () => { + return this.#lastSignerSig + } + + #process = ( + createSignature: string, + docSignatures: { [key: `npub1${string}`]: string } + ) => { + try { + const createSignatureEvent = parseNostrEvent(createSignature) + const { signers } = parseCreateSignatureEventContent( + createSignatureEvent.content + ) + const getPrevSignerSig = (npub: `npub1${string}`) => { + if (signers[0] === npub) { + return createSignatureEvent.sig + } + + // Find the index of signer + const currentSignerIndex = signers.findIndex( + (signer) => signer === npub + ) + + // Return if could not found user in signer's list + if (currentSignerIndex === -1) return + + // Find prev signer + const prevSigner = signers[currentSignerIndex - 1] + + // Get the signature of prev signer + return this.#signatures.get(prevSigner) + } + + this.#signers = [...signers] + for (const npub in docSignatures) { + try { + // Parse each signature event + const event = parseNostrEvent(docSignatures[npub as `npub1${string}`]) + this.#signatures.set(npub as `npub1${string}`, event.sig) + const isValidSignature = verifyEvent(event) + if (isValidSignature) { + const prevSignersSig = getPrevSignerSig(npub as `npub1${string}`) + const signedEvent: SignedEventContent = JSON.parse(event.content) + if ( + signedEvent.prevSig && + prevSignersSig && + signedEvent.prevSig === prevSignersSig + ) { + this.#signersStatus.set( + npub as `npub1${string}`, + SignStatus.Signed + ) + this.#lastSignerSig = event.sig + } + } else { + this.#signersStatus.set( + npub as `npub1${string}`, + SignStatus.Invalid + ) + } + } catch (error) { + this.#signersStatus.set(npub as `npub1${string}`, SignStatus.Invalid) + } + } + + this.#signers + .filter((s) => !this.#signatures.has(s)) + .forEach((s) => this.#signersStatus.set(s, SignStatus.Pending)) + + // Get the first signer that hasn't signed + const nextSigner = this.#signers.find((s) => !this.#signatures.has(s)) + if (nextSigner) { + this.#nextSigner = nextSigner + this.#signersStatus.set(nextSigner, SignStatus.Awaiting) + } + } catch (error) { + if (error instanceof MetaParseError) { + toast.error(error.message) + console.error(error.name, error.message, error.cause, error.context) + } else { + console.error('Unexpected error', error) + } + } + } +} diff --git a/src/store/actionTypes.ts b/src/store/actionTypes.ts index 90fa99b..9a76f3f 100644 --- a/src/store/actionTypes.ts +++ b/src/store/actionTypes.ts @@ -7,7 +7,7 @@ export const UPDATE_LOGIN_METHOD = 'UPDATE_LOGIN_METHOD' export const UPDATE_NOSTR_LOGIN_AUTH_METHOD = 'UPDATE_NOSTR_LOGIN_AUTH_METHOD' export const UPDATE_KEYPAIR = 'UPDATE_KEYPAIR' -export const SET_METADATA_EVENT = 'SET_METADATA_EVENT' +export const SET_USER_PROFILE = 'SET_USER_PROFILE' export const SET_USER_ROBOT_IMAGE = 'SET_USER_ROBOT_IMAGE' diff --git a/src/store/actions.ts b/src/store/actions.ts index bca5438..fd1fb47 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -2,7 +2,7 @@ import * as ActionTypes from './actionTypes' import { State } from './rootReducer' export * from './auth/action' -export * from './metadata/action' +export * from './user/action' export * from './relays/action' export * from './userAppData/action' diff --git a/src/store/metadata/action.ts b/src/store/metadata/action.ts deleted file mode 100644 index a36561a..0000000 --- a/src/store/metadata/action.ts +++ /dev/null @@ -1,8 +0,0 @@ -import * as ActionTypes from '../actionTypes' -import { SetMetadataEvent } from './types' -import { Event } from 'nostr-tools' - -export const setMetadataEvent = (payload: Event): SetMetadataEvent => ({ - type: ActionTypes.SET_METADATA_EVENT, - payload -}) diff --git a/src/store/metadata/reducer.ts b/src/store/metadata/reducer.ts deleted file mode 100644 index edb0571..0000000 --- a/src/store/metadata/reducer.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as ActionTypes from '../actionTypes' -import { MetadataDispatchTypes } from './types' -import { Event } from 'nostr-tools' - -const initialState: Event | null = null - -const reducer = ( - state = initialState, - action: MetadataDispatchTypes -): Event | null => { - switch (action.type) { - case ActionTypes.SET_METADATA_EVENT: - return { - ...action.payload - } - - case ActionTypes.RESTORE_STATE: - return action.payload.metadata || initialState - - default: - return state - } -} - -export default reducer diff --git a/src/store/metadata/types.ts b/src/store/metadata/types.ts deleted file mode 100644 index cbc38ef..0000000 --- a/src/store/metadata/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as ActionTypes from '../actionTypes' -import { Event } from 'nostr-tools' -import { RestoreState } from '../actions' - -export interface SetMetadataEvent { - type: typeof ActionTypes.SET_METADATA_EVENT - payload: Event -} - -export type MetadataDispatchTypes = SetMetadataEvent | RestoreState diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts index 61b2837..4f9ac70 100644 --- a/src/store/rootReducer.ts +++ b/src/store/rootReducer.ts @@ -1,37 +1,31 @@ -import { Event } from 'nostr-tools' import { combineReducers } from 'redux' import { UserAppData } from '../types' import * as ActionTypes from './actionTypes' import authReducer from './auth/reducer' import { AuthDispatchTypes, AuthState } from './auth/types' -import metadataReducer from './metadata/reducer' +import userReducer from './user/reducer' import relaysReducer from './relays/reducer' import { RelaysDispatchTypes, RelaysState } from './relays/types' import UserAppDataReducer from './userAppData/reducer' -import userRobotImageReducer from './userRobotImage/reducer' -import { MetadataDispatchTypes } from './metadata/types' import { UserAppDataDispatchTypes } from './userAppData/types' -import { UserRobotImageDispatchTypes } from './userRobotImage/types' +import { UserDispatchTypes, UserState } from './user/types' export interface State { auth: AuthState - metadata?: Event - userRobotImage?: string + user: UserState relays: RelaysState userAppData?: UserAppData } type AppActions = | AuthDispatchTypes - | MetadataDispatchTypes - | UserRobotImageDispatchTypes + | UserDispatchTypes | RelaysDispatchTypes | UserAppDataDispatchTypes export const appReducer = combineReducers({ auth: authReducer, - metadata: metadataReducer, - userRobotImage: userRobotImageReducer, + user: userReducer, relays: relaysReducer, userAppData: UserAppDataReducer }) diff --git a/src/store/user/action.ts b/src/store/user/action.ts new file mode 100644 index 0000000..5a1ead7 --- /dev/null +++ b/src/store/user/action.ts @@ -0,0 +1,17 @@ +import { NDKUserProfile } from '@nostr-dev-kit/ndk' +import * as ActionTypes from '../actionTypes' +import { SetUserProfile, SetUserRobotImage } from './types' + +export const setUserRobotImage = ( + payload: string | null +): SetUserRobotImage => ({ + type: ActionTypes.SET_USER_ROBOT_IMAGE, + payload +}) + +export const setUserProfile = ( + payload: NDKUserProfile | null +): SetUserProfile => ({ + type: ActionTypes.SET_USER_PROFILE, + payload +}) diff --git a/src/store/user/reducer.ts b/src/store/user/reducer.ts new file mode 100644 index 0000000..b48baca --- /dev/null +++ b/src/store/user/reducer.ts @@ -0,0 +1,34 @@ +import * as ActionTypes from '../actionTypes' +import { UserDispatchTypes, UserState } from './types' + +const initialState: UserState = { + robotImage: null, + profile: null +} + +const reducer = ( + state = initialState, + action: UserDispatchTypes +): UserState => { + switch (action.type) { + case ActionTypes.SET_USER_ROBOT_IMAGE: + return { + ...state, + robotImage: action.payload + } + + case ActionTypes.SET_USER_PROFILE: + return { + ...state, + profile: action.payload + } + + case ActionTypes.RESTORE_STATE: + return action.payload.user || initialState + + default: + return state + } +} + +export default reducer diff --git a/src/store/user/types.ts b/src/store/user/types.ts new file mode 100644 index 0000000..7f615f5 --- /dev/null +++ b/src/store/user/types.ts @@ -0,0 +1,23 @@ +import { NDKUserProfile } from '@nostr-dev-kit/ndk' +import * as ActionTypes from '../actionTypes' +import { RestoreState } from '../actions' + +export interface UserState { + robotImage: string | null + profile: NDKUserProfile | null +} + +export interface SetUserRobotImage { + type: typeof ActionTypes.SET_USER_ROBOT_IMAGE + payload: string | null +} + +export interface SetUserProfile { + type: typeof ActionTypes.SET_USER_PROFILE + payload: NDKUserProfile | null +} + +export type UserDispatchTypes = + | SetUserRobotImage + | SetUserProfile + | RestoreState diff --git a/src/store/userRobotImage/action.ts b/src/store/userRobotImage/action.ts deleted file mode 100644 index 5bec4ef..0000000 --- a/src/store/userRobotImage/action.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as ActionTypes from '../actionTypes' -import { SetUserRobotImage } from './types' - -export const setUserRobotImage = ( - payload: string | null -): SetUserRobotImage => ({ - type: ActionTypes.SET_USER_ROBOT_IMAGE, - payload -}) diff --git a/src/store/userRobotImage/reducer.ts b/src/store/userRobotImage/reducer.ts deleted file mode 100644 index db6bdbe..0000000 --- a/src/store/userRobotImage/reducer.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as ActionTypes from '../actionTypes' -import { UserRobotImageDispatchTypes } from './types' - -const initialState: string | null = null - -const reducer = ( - state = initialState, - action: UserRobotImageDispatchTypes -): string | null | undefined => { - switch (action.type) { - case ActionTypes.SET_USER_ROBOT_IMAGE: - return action.payload - - case ActionTypes.RESTORE_STATE: - return action.payload.userRobotImage || initialState - - default: - return state - } -} - -export default reducer diff --git a/src/store/userRobotImage/types.ts b/src/store/userRobotImage/types.ts deleted file mode 100644 index 2bef640..0000000 --- a/src/store/userRobotImage/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as ActionTypes from '../actionTypes' -import { RestoreState } from '../actions' - -export interface SetUserRobotImage { - type: typeof ActionTypes.SET_USER_ROBOT_IMAGE - payload: string | null -} - -export type UserRobotImageDispatchTypes = SetUserRobotImage | RestoreState diff --git a/src/types/core.ts b/src/types/core.ts index 3324ed5..932ebf5 100644 --- a/src/types/core.ts +++ b/src/types/core.ts @@ -1,6 +1,7 @@ import { Mark } from './mark' import { Keys } from '../store/auth/types' import { Event } from 'nostr-tools' +import { SigitStatus, SignStatus } from '../utils' export enum UserRole { signer = 'Signer', @@ -18,6 +19,7 @@ export interface Meta { docSignatures: { [key: `npub1${string}`]: string } exportSignature?: string keys?: { sender: string; keys: { [user: `npub1${string}`]: string } } + timestamps?: OpenTimestamp[] } export interface CreateSignatureEventContent { @@ -34,9 +36,23 @@ export interface SignedEventContent { marks: Mark[] } -export interface Sigit { - fileUrl: string - meta: Meta +export interface OpenTimestamp { + nostrId: string + value: string + verification?: OpenTimestampVerification + signature?: string +} + +export interface OpenTimestampVerification { + height: number + timestamp: number +} + +export interface OpenTimestampUpgradeVerifyResponse { + timestamp: OpenTimestamp + upgraded: boolean + verified?: boolean + verification?: OpenTimestampVerification } export interface UserAppData { @@ -63,3 +79,52 @@ export interface UserAppData { export interface DocSignatureEvent extends Event { parsedContent?: SignedEventContent } + +export interface SigitNotification { + metaUrl: string + keys?: { sender: string; keys: { [user: `npub1${string}`]: string } } +} + +export function isSigitNotification(obj: unknown): obj is SigitNotification { + return typeof (obj as SigitNotification).metaUrl === 'string' +} + +/** + * Flattened interface that combines properties `Meta`, `CreateSignatureEventContent`, + * and `Event` (event's fields are made optional and pubkey and created_at replaced with our versions) + */ +export interface FlatMeta + extends Meta, + CreateSignatureEventContent, + Partial> { + submittedBy?: string + + // Optional field only present on exported sigits + // Exporting adds user's pubkey + exportedBy?: string + + // Remove created_at and replace with createdAt + createdAt?: number + + // Validated create signature event + isValid: boolean + + // Decryption + encryptionKey: string | undefined + + // Parsed Document Signatures + parsedSignatureEvents: { + [signer: `npub1${string}`]: DocSignatureEvent + } + + // Calculated completion time + completedAt?: number + + // Calculated status fields + signedStatus: SigitStatus + signersStatus: { + [signer: `npub1${string}`]: SignStatus + } + + timestamps?: OpenTimestamp[] +} diff --git a/src/types/errors/MetaStorageError.ts b/src/types/errors/MetaStorageError.ts new file mode 100644 index 0000000..a5bc2cd --- /dev/null +++ b/src/types/errors/MetaStorageError.ts @@ -0,0 +1,26 @@ +import { Jsonable } from '.' + +export enum MetaStorageErrorType { + 'ENCRYPTION_KEY_REQUIRED' = 'Encryption key is required.', + 'HASHING_FAILED' = "Can't get encrypted file hash.", + 'FETCH_FAILED' = 'Fetching meta.json requires an encryption key.', + 'HASH_VERIFICATION_FAILED' = 'Unable to verify meta.json.', + 'DECRYPTION_FAILED' = 'Error decryping meta.json.', + 'UNHANDLED_FETCH_ERROR' = 'Unable to fetch meta.json. Something went wrong.' +} + +export class MetaStorageError extends Error { + public readonly context?: Jsonable + + constructor( + message: MetaStorageErrorType, + options: { cause?: Error; context?: Jsonable } = {} + ) { + const { cause, context } = options + + super(message, { cause }) + this.name = this.constructor.name + + this.context = context + } +} diff --git a/src/types/event.ts b/src/types/event.ts new file mode 100644 index 0000000..72c171c --- /dev/null +++ b/src/types/event.ts @@ -0,0 +1,5 @@ +export enum KeyboardCode { + Escape = 'Escape', + Enter = 'Enter', + NumpadEnter = 'NumpadEnter' +} diff --git a/src/types/index.ts b/src/types/index.ts index 6c9f259..5c5b715 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,6 +1,6 @@ export * from './cache' export * from './core' export * from './nostr' -export * from './profile' export * from './relay' export * from './zip' +export * from './event' diff --git a/src/types/mark.ts b/src/types/mark.ts index df733d6..e8ea327 100644 --- a/src/types/mark.ts +++ b/src/types/mark.ts @@ -8,13 +8,16 @@ export interface CurrentUserMark { currentValue?: string } +// Both PdfFileHash and FileHash currently exist. +// It enables backward compatibility for Sigits created before January 2025 export interface Mark { id: number npub: string - pdfFileHash: string type: MarkType location: MarkLocation fileName: string + pdfFileHash?: string + fileHash?: string value?: string } diff --git a/src/types/opentimestamps.d.ts b/src/types/opentimestamps.d.ts new file mode 100644 index 0000000..99ba447 --- /dev/null +++ b/src/types/opentimestamps.d.ts @@ -0,0 +1,38 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +interface OpenTimestamps { + // Create a detached timestamp file from a buffer or file hash + DetachedTimestampFile: { + fromHash(op: any, hash: Uint8Array): any + fromBytes(op: any, buffer: Uint8Array): any + deserialize(buffer: any): any + } + + // Stamp the provided timestamp file and return a Promise + stamp(file: any): Promise + + // Verify the provided timestamp proof file + verify( + ots: string, + file: string + ): Promise> + + // Other utilities or operations (like OpSHA256, serialization) + Ops: { + OpSHA256: any + OpSHA1?: any + } + + Context: { + StreamSerialization: any + } + + // Load a timestamp file from a buffer + deserialize(bytes: Uint8Array): any + + // Other potential methods based on repo functions + upgrade(file: any): Promise +} + +interface TimestampVerficiationResponse { + bitcoin: { timestamp: number; height: number } +} diff --git a/src/types/profile.ts b/src/types/profile.ts deleted file mode 100644 index 1dcfa6f..0000000 --- a/src/types/profile.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface ProfileMetadata { - name?: string - display_name?: string - /** @deprecated use name instead */ - username?: string - picture?: string - banner?: string - about?: string - website?: string - nip05?: string - lud16?: string -} diff --git a/src/types/relay.ts b/src/types/relay.ts index dd41095..401e5ee 100644 --- a/src/types/relay.ts +++ b/src/types/relay.ts @@ -1,3 +1,9 @@ +export enum UserRelaysType { + Read = 'readRelayUrls', + Write = 'writeRelayUrls', + Both = 'bothRelayUrls' +} + export interface RelaySet { read: string[] write: string[] diff --git a/src/types/system/index.d.ts b/src/types/system/index.d.ts index 81eb877..8f7abf7 100644 --- a/src/types/system/index.d.ts +++ b/src/types/system/index.d.ts @@ -3,5 +3,6 @@ import type { WindowNostr } from 'nostr-tools/nip07' declare global { interface Window { nostr?: WindowNostr + OpenTimestamps: OpenTimestamps } } diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..afd91f9 --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,44 @@ +import { Event } from 'nostr-tools' +import { SignedEvent } from '../types' +import { saveAuthToken } from './localStorage' + +export const base64EncodeSignedEvent = (event: SignedEvent) => { + try { + const authEventSerialized = JSON.stringify(event) + const token = btoa(authEventSerialized) + return token + } catch (error) { + throw new Error('An error occurred in JSON.stringify of signedAuthEvent') + } +} + +export const base64DecodeAuthToken = (authToken: string): SignedEvent => { + const decodedToken = atob(authToken) + + try { + const signedEvent = JSON.parse(decodedToken) + return signedEvent + } catch (error) { + throw new Error('An error occurred in JSON.parse of the auth token') + } +} + +export const createAndSaveAuthToken = (signedAuthEvent: SignedEvent) => { + const base64Encoded = base64EncodeSignedEvent(signedAuthEvent) + + // save newly created auth token (base64 nostr signed event) in local storage along with expiry time + saveAuthToken(base64Encoded) + return base64Encoded +} + +export const getEmptyMetadataEvent = (pubkey?: string): Event => { + return { + content: '', + created_at: new Date().valueOf(), + id: '', + kind: 0, + pubkey: pubkey || '', + sig: '', + tags: [] + } +} diff --git a/src/utils/const.ts b/src/utils/const.ts index 38f138e..2b8e822 100644 --- a/src/utils/const.ts +++ b/src/utils/const.ts @@ -112,3 +112,13 @@ export const MOST_COMMON_MEDIA_TYPES = new Map([ ['3g2', 'video/3gpp2'], // 3GPP2 audio/video container ['7z', 'application/x-7z-compressed'] // 7-zip archive ]) + +export const SIGNATURE_PAD_OPTIONS = { + minWidth: 0.5, + maxWidth: 3 +} as const + +export const SIGNATURE_PAD_SIZE = { + width: 300, + height: 150 +} diff --git a/src/utils/dvm.ts b/src/utils/dvm.ts deleted file mode 100644 index c2f33e8..0000000 --- a/src/utils/dvm.ts +++ /dev/null @@ -1,228 +0,0 @@ -import { EventTemplate, Filter, kinds, nip19 } from 'nostr-tools' -import { compareObjects, queryNip05, unixNow } from '.' -import { - MetadataController, - NostrController, - relayController -} from '../controllers' -import { NostrJoiningBlock, RelayInfoObject } from '../types' -import NDK, { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk' -import store from '../store/store' -import { setRelayInfoAction } from '../store/actions' - -export const getNostrJoiningBlockNumber = async ( - hexKey: string -): Promise => { - const metadataController = MetadataController.getInstance() - - const relaySet = await metadataController.findRelayListMetadata(hexKey) - - const userRelays: string[] = [] - - // find user's relays - if (relaySet.write.length > 0) { - userRelays.push(...relaySet.write) - } else { - const metadata = await metadataController.findMetadata(hexKey) - if (!metadata) return null - - const metadataContent = - metadataController.extractProfileMetadataContent(metadata) - - if (metadataContent?.nip05) { - const nip05Profile = await queryNip05(metadataContent.nip05) - - if (nip05Profile && nip05Profile.pubkey === hexKey) { - userRelays.push(...nip05Profile.relays) - } - } - } - - if (userRelays.length === 0) return null - - // filter for finding user's first kind 0 event - const eventFilter: Filter = { - kinds: [kinds.Metadata], - authors: [hexKey] - } - - // find user's kind 0 event published on user's relays - const event = await relayController.fetchEvent(eventFilter, userRelays) - - if (event) { - const { created_at } = event - - // initialize job request - const jobEventTemplate: EventTemplate = { - content: '', - created_at: unixNow(), - kind: 68001, - tags: [ - ['i', `${created_at * 1000}`], - ['j', 'blockChain-block-number'] - ] - } - - const nostrController = NostrController.getInstance() - - // sign job request event - const jobSignedEvent = await nostrController.signEvent(jobEventTemplate) - - const relays = [ - 'wss://relay.damus.io', - 'wss://relay.primal.net', - 'wss://relayable.org' - ] - - await relayController.publish(jobSignedEvent, relays).catch((err) => { - console.error( - 'Error occurred in publish blockChain-block-number DVM job', - err - ) - }) - - const subscribeWithTimeout = ( - subscription: NDKSubscription, - timeoutMs: number - ): Promise => { - return new Promise((resolve, reject) => { - const eventHandler = (event: NDKEvent) => { - subscription.stop() - resolve(event.content) - } - - subscription.on('event', eventHandler) - - // Set up a timeout to stop the subscription after a specified time - const timeout = setTimeout(() => { - subscription.stop() // Stop the subscription - reject(new Error('Subscription timed out')) // Reject the promise with a timeout error - }, timeoutMs) - - // Handle subscription close event - subscription.on('close', () => clearTimeout(timeout)) - }) - } - - const dvmNDK = new NDK({ - explicitRelayUrls: relays - }) - - await dvmNDK.connect(2000) - - // filter for getting DVM job's result - const sub = dvmNDK.subscribe({ - kinds: [68002 as number], - '#e': [jobSignedEvent.id], - '#p': [jobSignedEvent.pubkey] - }) - - // asynchronously get block number from dvm job with 20 seconds timeout - const dvmJobResult = await subscribeWithTimeout(sub, 20000) - - const encodedEventPointer = nip19.neventEncode({ - id: event.id, - relays: userRelays, - author: event.pubkey, - kind: event.kind - }) - - return { - block: parseInt(dvmJobResult), - encodedEventPointer - } - } - - return null -} - -/** - * Sets information about relays into relays.info app state. - * @param relayURIs - relay URIs to get information about - */ -export const getRelayInfo = async (relayURIs: string[]) => { - // initialize job request - const jobEventTemplate: EventTemplate = { - content: '', - created_at: unixNow(), - kind: 68001, - tags: [ - ['i', `${JSON.stringify(relayURIs)}`], - ['j', 'relay-info'] - ] - } - - const nostrController = NostrController.getInstance() - - // sign job request event - const jobSignedEvent = await nostrController.signEvent(jobEventTemplate) - - const relays = [ - 'wss://relay.damus.io', - 'wss://relay.primal.net', - 'wss://relayable.org' - ] - - // publish job request - await relayController.publish(jobSignedEvent, relays) - - console.log('jobSignedEvent :>> ', jobSignedEvent) - - const subscribeWithTimeout = ( - subscription: NDKSubscription, - timeoutMs: number - ): Promise => { - return new Promise((resolve, reject) => { - const eventHandler = (event: NDKEvent) => { - subscription.stop() - resolve(event.content) - } - - subscription.on('event', eventHandler) - - // Set up a timeout to stop the subscription after a specified time - const timeout = setTimeout(() => { - subscription.stop() // Stop the subscription - reject(new Error('Subscription timed out')) // Reject the promise with a timeout error - }, timeoutMs) - - // Handle subscription close event - subscription.on('close', () => clearTimeout(timeout)) - }) - } - - const dvmNDK = new NDK({ - explicitRelayUrls: relays - }) - - await dvmNDK.connect(2000) - - // filter for getting DVM job's result - const sub = dvmNDK.subscribe({ - kinds: [68002 as number], - '#e': [jobSignedEvent.id], - '#p': [jobSignedEvent.pubkey] - }) - - // asynchronously get block number from dvm job with 20 seconds timeout - const dvmJobResult = await subscribeWithTimeout(sub, 20000) - - if (!dvmJobResult) { - return Promise.reject(`Relay(s) information wasn't received`) - } - - let relaysInfo: RelayInfoObject - - try { - relaysInfo = JSON.parse(dvmJobResult) - } catch (error) { - return Promise.reject(`Invalid relay(s) information.`) - } - - if ( - relaysInfo && - !compareObjects(store.getState().relays?.info, relaysInfo) - ) { - store.dispatch(setRelayInfoAction(relaysInfo)) - } -} diff --git a/src/utils/file.ts b/src/utils/file.ts index 84b30fc..e8c4e33 100644 --- a/src/utils/file.ts +++ b/src/utils/file.ts @@ -1,7 +1,11 @@ +import { MARK_TYPE_CONFIG } from '../components/MarkTypeStrategy/MarkStrategy.tsx' +import { NostrController } from '../controllers/NostrController.ts' +import store from '../store/store.ts' import { Meta } from '../types' import { PdfPage } from '../types/drawing.ts' import { MOST_COMMON_MEDIA_TYPES } from './const.ts' import { extractMarksFromSignedMeta } from './mark.ts' +import { hexToNpub } from './nostr.ts' import { addMarks, groupMarksByFileNamePage, @@ -20,8 +24,50 @@ export const getZipWithFiles = async ( for (const [fileName, file] of Object.entries(files)) { // Handle PDF Files, add marks - if (file.isPdf) { - const blob = await addMarks(file, marksByFileNamePage[fileName]) + if (file.isPdf && fileName in marksByFileNamePage) { + const marksToAdd = marksByFileNamePage[fileName] + if (meta.keys) { + for (let i = 0; i < marks.length; i++) { + const m = marks[i] + const { sender, keys } = meta.keys + const usersPubkey = store.getState().auth.usersPubkey! + const usersNpub = hexToNpub(usersPubkey) + if (usersNpub in keys) { + const encryptionKey = await NostrController.getInstance() + .nip04Decrypt(sender, keys[usersNpub]) + .catch((err) => { + console.log( + 'An error occurred in decrypting encryption key', + err + ) + return null + }) + + try { + const { fetchAndDecrypt } = MARK_TYPE_CONFIG[m.type] || {} + if ( + typeof fetchAndDecrypt === 'function' && + m.value && + encryptionKey + ) { + // Fetch and decrypt the original file + const link = m.value.split('/') + const decrypted = await fetchAndDecrypt(m.value, encryptionKey) + + // Save decrypted + zip.file( + `signatures/${link[link.length - 1]}.json`, + new Blob([decrypted]) + ) + marks[i].value = decrypted + } + } catch (error) { + console.error(`Error during mark fetchAndDecrypt phase`, error) + } + } + } + } + const blob = await addMarks(file, marksToAdd) zip.file(`marked/${fileName}`, blob) } diff --git a/src/utils/index.ts b/src/utils/index.ts index accc008..274ceab 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,6 @@ +export * from './auth' +export * from './const' export * from './crypto' -export * from './dvm' export * from './hash' export * from './localStorage' export * from './mark' diff --git a/src/utils/mark.ts b/src/utils/mark.ts index b77818a..1868403 100644 --- a/src/utils/mark.ts +++ b/src/utils/mark.ts @@ -24,6 +24,7 @@ import { faStamp, faTableCellsLarge } from '@fortawesome/free-solid-svg-icons' +import { MARK_TYPE_CONFIG } from '../components/MarkTypeStrategy/MarkStrategy.tsx' /** * Takes in an array of Marks already filtered by User. @@ -122,15 +123,19 @@ const isLast = (index: number, arr: T[]) => index === arr.length - 1 const isCurrentValueLast = ( currentUserMarks: CurrentUserMark[], - selectedMark: CurrentUserMark, + selectedMark: CurrentUserMark | null, selectedMarkValue: string ) => { - const filteredMarks = currentUserMarks.filter( - (mark) => mark.id !== selectedMark.id - ) - return ( - isCurrentUserMarksComplete(filteredMarks) && selectedMarkValue.length > 0 - ) + if (selectedMark && currentUserMarks.length > 0) { + const filteredMarks = currentUserMarks.filter( + (mark) => mark.id !== selectedMark.id + ) + return ( + isCurrentUserMarksComplete(filteredMarks) && selectedMarkValue.length > 0 + ) + } + + return true } const getUpdatedMark = ( @@ -158,6 +163,11 @@ export const DEFAULT_TOOLBOX: DrawTool[] = [ icon: faT, label: 'Text' }, + { + identifier: MarkType.SIGNATURE, + icon: faSignature, + label: 'Signature' + }, { identifier: MarkType.FULLNAME, icon: faIdCard, @@ -170,12 +180,6 @@ export const DEFAULT_TOOLBOX: DrawTool[] = [ label: 'Job Title', isComingSoon: true }, - { - identifier: MarkType.SIGNATURE, - icon: faSignature, - label: 'Signature', - isComingSoon: true - }, { identifier: MarkType.DATETIME, icon: faClock, @@ -266,6 +270,29 @@ export const getToolboxLabelByMarkType = (markType: MarkType) => { return DEFAULT_TOOLBOX.find((t) => t.identifier === markType)?.label } +export const encryptAndUploadMarks = async ( + marks: Mark[], + encryptionKey?: string +) => { + const _marks = [...marks] + for (let i = 0; i < _marks.length; i++) { + const mark = _marks[i] + const hasProcess = + mark.type in MARK_TYPE_CONFIG && + typeof MARK_TYPE_CONFIG[mark.type]?.encryptAndUpload === 'function' + + if (hasProcess) { + const value = mark.value! + const processFn = MARK_TYPE_CONFIG[mark.type]?.encryptAndUpload + if (processFn) { + mark.value = await processFn(value, encryptionKey) + } + } + } + + return _marks +} + export { getCurrentUserMarks, filterMarksByPubkey, diff --git a/src/utils/meta.ts b/src/utils/meta.ts index c915f66..75e1654 100644 --- a/src/utils/meta.ts +++ b/src/utils/meta.ts @@ -1,5 +1,12 @@ import { CreateSignatureEventContent, Meta } from '../types' -import { fromUnixTimestamp, parseJson } from '.' +import { + decryptArrayBuffer, + encryptArrayBuffer, + fromUnixTimestamp, + getHash, + parseJson, + uploadToFileStorage +} from '.' import { Event, verifyEvent } from 'nostr-tools' import { toast } from 'react-toastify' import { extractFileExtensions } from './file' @@ -8,6 +15,11 @@ import { MetaParseError, MetaParseErrorType } from '../types/errors/MetaParseError' +import axios from 'axios' +import { + MetaStorageError, + MetaStorageErrorType +} from '../types/errors/MetaStorageError' export enum SignStatus { Signed = 'Signed', @@ -37,9 +49,9 @@ export interface SigitCardDisplayInfo { * @param raw Raw string for parsing * @returns parsed Event */ -export const parseNostrEvent = async (raw: string): Promise => { +export const parseNostrEvent = (raw: string): Event => { try { - const event = await parseJson(raw) + const event = JSON.parse(raw) as Event return event } catch (error) { throw new MetaParseError(MetaParseErrorType.PARSE_ERROR_EVENT, { @@ -54,12 +66,13 @@ export const parseNostrEvent = async (raw: string): Promise => { * @param raw Raw string for parsing * @returns parsed CreateSignatureEventContent */ -export const parseCreateSignatureEventContent = async ( +export const parseCreateSignatureEventContent = ( raw: string -): Promise => { +): CreateSignatureEventContent => { try { - const createSignatureEventContent = - await parseJson(raw) + const createSignatureEventContent = JSON.parse( + raw + ) as CreateSignatureEventContent return createSignatureEventContent } catch (error) { throw new MetaParseError( @@ -77,7 +90,7 @@ export const parseCreateSignatureEventContent = async ( * @param meta Sigit metadata * @returns SigitCardDisplayInfo */ -export const extractSigitCardDisplayInfo = async (meta: Meta) => { +export const extractSigitCardDisplayInfo = (meta: Meta) => { if (!meta?.createSignature) return const sigitInfo: SigitCardDisplayInfo = { @@ -88,14 +101,14 @@ export const extractSigitCardDisplayInfo = async (meta: Meta) => { } try { - const createSignatureEvent = await parseNostrEvent(meta.createSignature) + const createSignatureEvent = parseNostrEvent(meta.createSignature) sigitInfo.isValid = verifyEvent(createSignatureEvent) // created_at in nostr events are stored in seconds sigitInfo.createdAt = fromUnixTimestamp(createSignatureEvent.created_at) - const createSignatureContent = await parseCreateSignatureEventContent( + const createSignatureContent = parseCreateSignatureEventContent( createSignatureEvent.content ) @@ -126,3 +139,76 @@ export const extractSigitCardDisplayInfo = async (meta: Meta) => { } } } + +export const uploadMetaToFileStorage = async ( + meta: Meta, + encryptionKey: string | undefined +) => { + // Value is the stringified meta object + const value = JSON.stringify(meta) + const encoder = new TextEncoder() + + // Encode it to the arrayBuffer + const uint8Array = encoder.encode(value) + + if (!encryptionKey) { + throw new MetaStorageError(MetaStorageErrorType.ENCRYPTION_KEY_REQUIRED) + } + + // Encrypt the file contents with the same encryption key from the create signature + const encryptedArrayBuffer = await encryptArrayBuffer( + uint8Array, + encryptionKey + ) + + const hash = await getHash(encryptedArrayBuffer) + if (!hash) { + throw new MetaStorageError(MetaStorageErrorType.HASHING_FAILED) + } + + // Create the encrypted json file from array buffer and hash + const file = new File([encryptedArrayBuffer], `${hash}.json`) + const url = await uploadToFileStorage(file) + + return url +} + +export const fetchMetaFromFileStorage = async ( + url: string, + encryptionKey: string | undefined +) => { + if (!encryptionKey) { + throw new MetaStorageError(MetaStorageErrorType.ENCRYPTION_KEY_REQUIRED) + } + + const encryptedArrayBuffer = await axios.get(url, { + responseType: 'arraybuffer' + }) + + // Verify hash + const parts = url.split('/') + const urlHash = parts[parts.length - 1] + const hash = await getHash(encryptedArrayBuffer.data) + if (hash !== urlHash) { + throw new MetaStorageError(MetaStorageErrorType.HASH_VERIFICATION_FAILED) + } + + const arrayBuffer = await decryptArrayBuffer( + encryptedArrayBuffer.data, + encryptionKey + ).catch((err) => { + throw new MetaStorageError(MetaStorageErrorType.DECRYPTION_FAILED, { + cause: err + }) + }) + + if (arrayBuffer) { + // Decode meta.json and parse + const decoder = new TextDecoder() + const json = decoder.decode(arrayBuffer) + const meta = await parseJson(json) + return meta + } + + throw new MetaStorageError(MetaStorageErrorType.UNHANDLED_FETCH_ERROR) +} diff --git a/src/utils/nostr.ts b/src/utils/nostr.ts index 2046b38..17030ad 100644 --- a/src/utils/nostr.ts +++ b/src/utils/nostr.ts @@ -1,17 +1,16 @@ -import { bytesToHex, hexToBytes } from '@noble/hashes/utils' +import { hexToBytes } from '@noble/hashes/utils' +import { NDKEvent, NDKUserProfile } from '@nostr-dev-kit/ndk' import axios from 'axios' -import _, { truncate } from 'lodash' +import { truncate } from 'lodash' import { Event, EventTemplate, - Filter, UnsignedEvent, VerifiedEvent, finalizeEvent, generateSecretKey, getEventHash, getPublicKey, - kinds, nip04, nip19, nip44, @@ -19,30 +18,17 @@ import { } from 'nostr-tools' import { toast } from 'react-toastify' import { NIP05_REGEX } from '../constants' -import { - MetadataController, - NostrController, - relayController, - RelayController -} from '../controllers' -import { - updateProcessedGiftWraps, - updateUserAppData as updateUserAppDataAction -} from '../store/actions' -import { Keys } from '../store/auth/types' import store from '../store/store' -import { Meta, ProfileMetadata, SignedEvent, UserAppData } from '../types' -import { getDefaultRelayMap } from './relays' -import { parseJson, removeLeadingSlash } from './string' -import { timeout } from './utils' -import { getHash } from './hash' +import { Meta, SignedEvent } from '../types' import { SIGIT_BLOSSOM } from './const.ts' +import { getHash } from './hash' +import { parseJson, removeLeadingSlash } from './string' import { SendDMError, SendDMErrorType } from '../types/errors/SendDMError.ts' /** * Generates a `d` tag for userAppData */ -const getDTagForUserAppData = async (): Promise => { +export const getDTagForUserAppData = async (): Promise => { const isLoggedIn = store.getState().auth.loggedIn const pubkey = store.getState().auth?.usersPubkey @@ -201,27 +187,6 @@ export const queryNip05 = async ( } } -export const base64EncodeSignedEvent = (event: SignedEvent) => { - try { - const authEventSerialized = JSON.stringify(event) - const token = btoa(authEventSerialized) - return token - } catch (error) { - throw new Error('An error occurred in JSON.stringify of signedAuthEvent') - } -} - -export const base64DecodeAuthToken = (authToken: string): SignedEvent => { - const decodedToken = atob(authToken) - - try { - const signedEvent = JSON.parse(decodedToken) - return signedEvent - } catch (error) { - throw new Error('An error occurred in JSON.parse of the auth token') - } -} - /** * @param pubkey in hex or npub format * @returns robohash.org url for the avatar @@ -361,317 +326,7 @@ export const createWrap = ( } } -/** - * Fetches user application data based on user's public key and stored metadata. - * - * @returns The user application data or null if an error occurs or no data is found. - */ -export const getUsersAppData = async (): Promise => { - // Initialize an array to hold relay URLs - const relays: string[] = [] - - // Retrieve the user's public key and relay map from the Redux store - const usersPubkey = store.getState().auth.usersPubkey! - const relayMap = store.getState().relays?.map - - // Check if relayMap is undefined in the Redux store - if (!relayMap) { - // If relayMap is not present, fetch relay list metadata - const metadataController = MetadataController.getInstance() - const relaySet = await metadataController - .findRelayListMetadata(usersPubkey) - .catch((err) => { - // Log error and return null if fetching metadata fails - console.log( - `An error occurred while finding relay list metadata for ${hexToNpub(usersPubkey)}`, - err - ) - return null - }) - - // Return null if metadata retrieval failed - if (!relaySet) return null - - // Ensure that the relay list is not empty - if (relaySet.write.length === 0) return null - - // Add write relays to the relays array - relays.push(...relaySet.write) - } else { - // If relayMap exists, filter and add write relays from the stored map - const writeRelays = Object.keys(relayMap).filter( - (key) => relayMap[key].write - ) - relays.push(...writeRelays) - } - - // Generate an identifier for the user's nip78 - const dTag = await getDTagForUserAppData() - if (!dTag) return null - - // Define a filter for fetching events - const filter: Filter = { - kinds: [kinds.Application], - '#d': [dTag] - } - - const encryptedContent = await relayController - .fetchEvent(filter, relays) - .then((event) => { - if (event) return event.content - - // If no event is found, return an empty stringified object - return '{}' - }) - .catch((err) => { - // Log error and show a toast notification if fetching event fails - console.log(`An error occurred in finding kind 30078 event`, err) - toast.error( - 'An error occurred in finding kind 30078 event for data storage' - ) - return null - }) - - // Return null if encrypted content retrieval fails - if (!encryptedContent) return null - - // Handle case where the encrypted content is an empty object - if (encryptedContent === '{}') { - // Generate ephemeral key pair - const secret = generateSecretKey() - const pubKey = getPublicKey(secret) - - return { - sigits: {}, - processedGiftWraps: [], - blossomUrls: [], - keyPair: { - private: bytesToHex(secret), - public: pubKey - } - } - } - - // Get an instance of the NostrController - const nostrController = NostrController.getInstance() - - // Decrypt the encrypted content - const decrypted = await nostrController - .nip04Decrypt(usersPubkey, encryptedContent) - .catch((err) => { - // Log error and show a toast notification if decryption fails - console.log('An error occurred while decrypting app data', err) - toast.error('An error occurred while decrypting app data') - return null - }) - - // Return null if decryption fails - if (!decrypted) return null - - // Parse the decrypted content - const parsedContent = await parseJson<{ - blossomUrls: string[] - keyPair: Keys - }>(decrypted).catch((err) => { - // Log error and show a toast notification if parsing fails - console.log( - 'An error occurred in parsing the content of kind 30078 event', - err - ) - toast.error('An error occurred in parsing the content of kind 30078 event') - return null - }) - - // Return null if parsing fails - if (!parsedContent) return null - - const { blossomUrls, keyPair } = parsedContent - - // Return null if no blossom URLs are found - if (blossomUrls.length === 0) return null - - // Fetch additional user app data from the first blossom URL - const dataFromBlossom = await getUserAppDataFromBlossom( - blossomUrls[0], - keyPair.private - ) - - // Return null if fetching data from blossom fails - if (!dataFromBlossom) return null - - const { sigits, processedGiftWraps } = dataFromBlossom - - // Return the final user application data - return { - blossomUrls, - keyPair, - sigits, - processedGiftWraps - } -} - -export const updateUsersAppData = async (meta: Meta) => { - const appData = store.getState().userAppData - if (!appData || !appData.keyPair) return null - - const sigits = _.cloneDeep(appData.sigits) - - const createSignatureEvent = await parseJson( - meta.createSignature - ).catch((err) => { - console.log('err in parsing the createSignature event:>> ', err) - toast.error( - err.message || 'error occurred in parsing the create signature event' - ) - return null - }) - - if (!createSignatureEvent) return null - - const id = createSignatureEvent.id - let isUpdated = false - - // check if sigit already exists - if (id in sigits) { - // update meta only if incoming meta is more recent - // than already existing one - const existingMeta = sigits[id] - if (existingMeta.modifiedAt < meta.modifiedAt) { - sigits[id] = meta - isUpdated = true - } - } else { - sigits[id] = meta - isUpdated = true - } - - if (!isUpdated) return null - - const blossomUrls = [...appData.blossomUrls] - - const newBlossomUrl = await uploadUserAppDataToBlossom( - sigits, - appData.processedGiftWraps, - appData.keyPair.private - ).catch((err) => { - console.log( - 'An error occurred in uploading user app data file to blossom server', - err - ) - toast.error( - 'An error occurred in uploading user app data file to blossom server' - ) - return null - }) - - if (!newBlossomUrl) return null - - // insert new blossom url at the start of the array - blossomUrls.unshift(newBlossomUrl) - - // only keep last 10 blossom urls, delete older ones - if (blossomUrls.length > 10) { - const filesToDelete = blossomUrls.splice(10) - filesToDelete.forEach((url) => { - deleteBlossomFile(url, appData.keyPair!.private).catch((err) => { - console.log( - 'An error occurred in removing old file of user app data from blossom server', - err - ) - }) - }) - } - - const usersPubkey = store.getState().auth.usersPubkey! - - // encrypt content for storing in kind 30078 event - const nostrController = NostrController.getInstance() - const encryptedContent = await nostrController - .nip04Encrypt( - usersPubkey, - JSON.stringify({ - blossomUrls, - keyPair: appData.keyPair - }) - ) - .catch((err) => { - console.log( - 'An error occurred in encryption of content for app data', - err - ) - toast.error( - err.message || 'An error occurred in encryption of content for app data' - ) - return null - }) - - if (!encryptedContent) return null - - // generate the identifier for user's appData event - const dTag = await getDTagForUserAppData() - if (!dTag) return null - - const updatedEvent: UnsignedEvent = { - kind: kinds.Application, - pubkey: usersPubkey!, - created_at: unixNow(), - tags: [['d', dTag]], - content: encryptedContent - } - - const signedEvent = await nostrController - .signEvent(updatedEvent) - .catch((err) => { - console.log('An error occurred in signing event', err) - toast.error(err.message || 'An error occurred in signing event') - return null - }) - - if (!signedEvent) return null - - const relayMap = store.getState().relays.map || getDefaultRelayMap() - const writeRelays = Object.keys(relayMap).filter((key) => relayMap[key].write) - - const publishResult = await Promise.race([ - relayController.publish(signedEvent, writeRelays), - timeout(40 * 1000) - ]).catch((err) => { - console.log('err :>> ', err) - if (err.message === 'Timeout') { - toast.error('Timeout occurred in publishing updated app data') - } else if (Array.isArray(err)) { - err.forEach((errResult) => { - toast.error( - `Publishing to ${errResult.relay} caused the following error: ${errResult.error}` - ) - }) - } else { - toast.error( - 'An unexpected error occurred in publishing updated app data ' - ) - } - - return null - }) - - if (!publishResult) return null - - // update redux store - store.dispatch( - updateUserAppDataAction({ - sigits, - blossomUrls, - processedGiftWraps: [...appData.processedGiftWraps], - keyPair: { - ...appData.keyPair - } - }) - ) - - return signedEvent -} - -const deleteBlossomFile = async (url: string, privateKey: string) => { +export const deleteBlossomFile = async (url: string, privateKey: string) => { const pathname = new URL(url).pathname const hash = removeLeadingSlash(pathname) @@ -706,7 +361,7 @@ const deleteBlossomFile = async (url: string, privateKey: string) => { * @param privateKey - The private key used for encryption. * @returns A promise that resolves to the URL of the uploaded file. */ -const uploadUserAppDataToBlossom = async ( +export const uploadUserAppDataToBlossom = async ( sigits: { [key: string]: Meta }, processedGiftWraps: string[], privateKey: string @@ -774,7 +429,10 @@ const uploadUserAppDataToBlossom = async ( * @param privateKey - The private key used for decryption. * @returns A promise that resolves to the decrypted and parsed user application data. */ -const getUserAppDataFromBlossom = async (url: string, privateKey: string) => { +export const getUserAppDataFromBlossom = async ( + url: string, + privateKey: string +) => { // Initialize errorCode to track HTTP error codes let errorCode = 0 @@ -843,152 +501,6 @@ const getUserAppDataFromBlossom = async (url: string, privateKey: string) => { return parsedContent } -/** - * Function to subscribe to sigits notifications for a specified public key. - * @param pubkey - The public key to subscribe to. - * @returns A promise that resolves when the subscription is successful. - */ -export const subscribeForSigits = async (pubkey: string) => { - // Instantiate the MetadataController to retrieve relay list metadata - const metadataController = MetadataController.getInstance() - const relaySet = await metadataController - .findRelayListMetadata(pubkey) - .catch((err) => { - // Log an error if retrieving relay list metadata fails - console.log( - `An error occurred while finding relay list metadata for ${hexToNpub(pubkey)}`, - err - ) - return null - }) - - // Return if metadata retrieval failed - if (!relaySet) return - - // Ensure relay list is not empty - if (relaySet.read.length === 0) return - - // Define the filter for the subscription - const filter: Filter = { - kinds: [1059], - '#p': [pubkey] - } - - // Process the received event synchronously - const events = await relayController.fetchEvents(filter, relaySet.read) - for (const e of events) { - await processReceivedEvent(e) - } - - // Async processing of the events has a race condition - // relayController.subscribeForEvents(filter, relaySet.read, (event) => { - // processReceivedEvent(event) - // }) -} - -const processReceivedEvent = async (event: Event, difficulty: number = 5) => { - const processedEvents = store.getState().userAppData?.processedGiftWraps - - // Abort processing if userAppData is undefined - if (!processedEvents) return - - if (processedEvents.includes(event.id)) return - - store.dispatch(updateProcessedGiftWraps([...processedEvents, event.id])) - - // validate PoW - // Count the number of leading zero bits in the hash - const leadingZeroes = countLeadingZeroes(event.id) - if (leadingZeroes < difficulty) return - - // decrypt the content of gift wrap event - const nostrController = NostrController.getInstance() - const decrypted = await nostrController.nip44Decrypt( - event.pubkey, - event.content - ) - - const internalUnsignedEvent = await parseJson(decrypted).catch( - (err) => { - console.log( - 'An error occurred in parsing the internal unsigned event', - err - ) - return null - } - ) - - if (!internalUnsignedEvent || internalUnsignedEvent.kind !== 938) return - - const meta = await parseJson(internalUnsignedEvent.content).catch( - (err) => { - console.log( - 'An error occurred in parsing the internal unsigned event', - err - ) - return null - } - ) - - if (!meta) return - - await updateUsersAppData(meta) -} - -/** - * Function to send a notification to a specified receiver. - * @param receiver - The recipient's public key. - * @param meta - Metadata associated with the notification. - */ -export const sendNotification = async (receiver: string, meta: Meta) => { - // Retrieve the user's public key from the state - const usersPubkey = store.getState().auth.usersPubkey! - - // Create an unsigned event object with the provided metadata - const unsignedEvent: UnsignedEvent = { - kind: 938, - pubkey: usersPubkey, - content: JSON.stringify(meta), - tags: [], - created_at: unixNow() - } - - // Wrap the unsigned event with the receiver's information - const wrappedEvent = createWrap(unsignedEvent, receiver) - - // Instantiate the MetadataController to retrieve relay list metadata - const metadataController = MetadataController.getInstance() - const relaySet = await metadataController - .findRelayListMetadata(receiver) - .catch((err) => { - // Log an error if retrieving relay list metadata fails - console.log( - `An error occurred while finding relay list metadata for ${hexToNpub(receiver)}`, - err - ) - return null - }) - - // Return if metadata retrieval failed - if (!relaySet) return - - // Ensure relay list is not empty - if (relaySet.read.length === 0) return - - // Publish the notification event to the recipient's read relays - await Promise.race([ - relayController.publish(wrappedEvent, relaySet.read), - timeout(40 * 1000) - ]).catch((err) => { - // Log an error if publishing the notification event fails - console.log( - `An error occurred while publishing notification event for ${hexToNpub(receiver)}`, - err - ) - throw err - }) -} - /** * Show user's name, first available in order: display_name, name, or npub as fallback * @param npub User identifier, it can be either pubkey or npub1 (we only show npub) @@ -996,9 +508,9 @@ export const sendNotification = async (receiver: string, meta: Meta) => { */ export const getProfileUsername = ( npub: `npub1${string}` | string, - profile?: ProfileMetadata + profile?: NDKUserProfile ) => - truncate(profile?.display_name || profile?.name || hexToNpub(npub), { + truncate(profile?.displayName || profile?.name || hexToNpub(npub), { length: 16 }) @@ -1143,3 +655,24 @@ export const sendPrivateDirectMessage = async ( // Return true indicating that the DM was successfully sent return true } + +/** + * Orders an array of NDKEvent objects chronologically based on their `created_at` property. + * + * @param events - The array of NDKEvent objects to be sorted. + * @param reverse - Optional flag to reverse the sorting order. + * If true, sorts in ascending order (oldest first), otherwise sorts in descending order (newest first). + * + * @returns The sorted array of events. + */ +export function orderEventsChronologically( + events: NDKEvent[], + reverse: boolean = false +): NDKEvent[] { + events.sort((e1: NDKEvent, e2: NDKEvent) => { + if (reverse) return e1.created_at! - e2.created_at! + else return e2.created_at! - e1.created_at! + }) + + return events +} diff --git a/src/utils/opentimestamps.ts b/src/utils/opentimestamps.ts new file mode 100644 index 0000000..b8fc8fe --- /dev/null +++ b/src/utils/opentimestamps.ts @@ -0,0 +1,119 @@ +import { OpenTimestamp, OpenTimestampUpgradeVerifyResponse } from '../types' +import { retry } from './retry.ts' +import { bytesToHex } from '@noble/hashes/utils' +import { utf8Encoder } from 'nostr-tools/utils' +import { hexStringToUint8Array } from './string.ts' + +/** + * Generates a timestamp for the provided nostr event ID. + * @returns Timestamp with its value and the nostr event ID. + */ +export const generateTimestamp = async ( + nostrId: string +): Promise => { + try { + return { + value: await retry(() => timestamp(nostrId)), + nostrId: nostrId + } + } catch (error) { + console.error(error) + return + } +} + +/** + * Attempts to upgrade (i.e. add Bitcoin blockchain attestations) and verify the provided timestamp. + * Returns the same timestamp, alongside additional information required to decide if any further + * timestamp updates are required. + * @param timestamp + */ +export const upgradeAndVerifyTimestamp = async ( + timestamp: OpenTimestamp +): Promise => { + const upgradedResult = await upgrade(timestamp) + return await verify(upgradedResult) +} + +/** + * Attempts to upgrade a timestamp. If an upgrade is available, + * it will add new data to detachedTimestamp. + * The upgraded flag indicates if an upgrade has been performed. + * @param t - timestamp + */ +export const upgrade = async ( + t: OpenTimestamp +): Promise => { + const detachedTimestamp = + window.OpenTimestamps.DetachedTimestampFile.deserialize( + hexStringToUint8Array(t.value) + ) + + const changed: boolean = + await window.OpenTimestamps.upgrade(detachedTimestamp) + if (changed) { + const updated = detachedTimestamp.serializeToBytes() + + const value = { + ...t, + timestamp: bytesToHex(updated) + } + + return { + timestamp: value, + upgraded: true + } + } + return { + timestamp: t, + upgraded: false + } +} + +/** + * Attempts to verify a timestamp. If verification is available, + * it will be included in the returned object. + * @param t - timestamp + */ +export const verify = async ( + t: OpenTimestampUpgradeVerifyResponse +): Promise => { + const detachedNostrId = window.OpenTimestamps.DetachedTimestampFile.fromBytes( + new window.OpenTimestamps.Ops.OpSHA256(), + utf8Encoder.encode(t.timestamp.nostrId) + ) + + const detachedTimestamp = + window.OpenTimestamps.DetachedTimestampFile.deserialize( + hexStringToUint8Array(t.timestamp.value) + ) + + const res = await window.OpenTimestamps.verify( + detachedTimestamp, + detachedNostrId + ) + + return { + ...t, + verified: !!res.bitcoin, + verification: res?.bitcoin || null + } +} + +/** + * Timestamps a nostrId. + * @param nostrId + */ +const timestamp = async (nostrId: string): Promise => { + const detachedTimestamp = + window.OpenTimestamps.DetachedTimestampFile.fromBytes( + new window.OpenTimestamps.Ops.OpSHA256(), + utf8Encoder.encode(nostrId) + ) + + await window.OpenTimestamps.stamp(detachedTimestamp) + const ctx = new window.OpenTimestamps.Context.StreamSerialization() + detachedTimestamp.serialize(ctx) + const timestampBytes = ctx.getOutput() + return bytesToHex(timestampBytes) +} diff --git a/src/utils/pdf.ts b/src/utils/pdf.ts index c3e381d..88cdc67 100644 --- a/src/utils/pdf.ts +++ b/src/utils/pdf.ts @@ -1,4 +1,4 @@ -import { PdfPage } from '../types/drawing.ts' +import { MarkType, PdfPage } from '../types/drawing.ts' import { PDFDocument, PDFFont, PDFPage, rgb } from 'pdf-lib' import { Mark } from '../types/mark.ts' import * as PDFJS from 'pdfjs-dist' @@ -11,6 +11,9 @@ if (!PDFJS.GlobalWorkerOptions.workerPort) { import fontkit from '@pdf-lib/fontkit' import defaultFont from '../assets/fonts/roboto-regular.ttf' +import { BasicPoint } from 'signature_pad/dist/types/point' +import SignaturePad from 'signature_pad' +import { SIGNATURE_PAD_OPTIONS, SIGNATURE_PAD_SIZE } from './const.ts' /** * Defined font size used when generating a PDF. Currently it is difficult to fully @@ -132,9 +135,18 @@ export const addMarks = async ( for (let i = 0; i < pages.length; i++) { if (marksPerPage && Object.hasOwn(marksPerPage, i)) { - marksPerPage[i]?.forEach((mark) => - drawMarkText(mark, pages[i], robotoFont) - ) + for (let j = 0; j < marksPerPage[i].length; j++) { + const mark = marksPerPage[i][j] + switch (mark.type) { + case MarkType.SIGNATURE: + await embedSignaturePng(mark, pages[i], pdf) + break + + default: + drawMarkText(mark, pages[i], robotoFont) + break + } + } } } @@ -245,3 +257,42 @@ async function embedFont(pdf: PDFDocument) { const embeddedFont = await pdf.embedFont(fontBytes) return embeddedFont } + +const embedSignaturePng = async ( + mark: Mark, + page: PDFPage, + pdf: PDFDocument +) => { + const { location } = mark + const { height } = page.getSize() + + if (hasValue(mark)) { + const data = JSON.parse(mark.value!).map((p: BasicPoint[]) => ({ + points: p + })) + const canvas = document.createElement('canvas') + canvas.width = SIGNATURE_PAD_SIZE.width + canvas.height = SIGNATURE_PAD_SIZE.height + const pad = new SignaturePad(canvas, SIGNATURE_PAD_OPTIONS) + pad.fromData(data) + const signatureImage = await pdf.embedPng(pad.toDataURL()) + + const scaled = signatureImage.scaleToFit(location.width, location.height) + + // Convert the mark location origin (top, left) to PDF origin (bottom, left) + // and center the image + const x = location.left + (location.width - scaled.width) / 2 + const y = + height - + location.top - + location.height + + (location.height - scaled.height) / 2 + + page.drawImage(signatureImage, { + x, + y, + width: scaled.width, + height: scaled.height + }) + } +} diff --git a/src/utils/relays.ts b/src/utils/relays.ts index c7be280..ef351d9 100644 --- a/src/utils/relays.ts +++ b/src/utils/relays.ts @@ -1,174 +1,42 @@ -import { Event, Filter, kinds, UnsignedEvent } from 'nostr-tools' -import { RelayList } from 'nostr-tools/kinds' -import { getRelayInfo, unixNow } from '.' -import { NostrController, relayController } from '../controllers' -import { localCache } from '../services' -import { RelayMap, RelaySet } from '../types' -import { - DEFAULT_LOOK_UP_RELAY_LIST, - ONE_DAY_IN_MS, - ONE_WEEK_IN_MS, - SIGIT_RELAY -} from './const' +import NDK, { NDKEvent, NDKRelayList } from '@nostr-dev-kit/ndk' +import { kinds, UnsignedEvent } from 'nostr-tools' +import { normalizeWebSocketURL, unixNow } from '.' +import { NostrController } from '../controllers' +import { RelayMap } from '../types' +import { SIGIT_RELAY } from './const' -const READ_MARKER = 'read' -const WRITE_MARKER = 'write' +export const getRelayMapFromNDKRelayList = (ndkRelayList: NDKRelayList) => { + const relayMap: RelayMap = {} -/** - * Attempts to find a relay list from the provided lookUpRelays. - * If the relay list is found, it will be added to the user relay list metadata. - * @param lookUpRelays - * @param hexKey - * @return found relay list or null - */ -const findRelayListAndUpdateCache = async ( - lookUpRelays: string[], - hexKey: string -): Promise => { - try { - const eventFilter: Filter = { - kinds: [RelayList], - authors: [hexKey] + ndkRelayList.readRelayUrls.forEach((relayUrl) => { + const normalizedUrl = normalizeWebSocketURL(relayUrl) + + relayMap[normalizedUrl] = { + read: true, + write: false } + }) - const event = await relayController.fetchEvent(eventFilter, lookUpRelays) - if (event) { - await localCache.addUserRelayListMetadata(event) + ndkRelayList.writeRelayUrls.forEach((relayUrl) => { + const normalizedUrl = normalizeWebSocketURL(relayUrl) + + const existing = relayMap[normalizedUrl] + if (existing) { + existing.write = true + } else { + relayMap[normalizedUrl] = { + read: false, + write: true + } } - return event - } catch (error) { - console.error(error) - return null - } + }) + + return relayMap } -/** - * Attempts to find a relay list in cache. If it is present, it will check that the cached event is not - * older than one week. - * @param hexKey - * @return RelayList event if it's not older than a week; otherwise null - */ -const findRelayListInCache = async (hexKey: string): Promise => { - try { - // Attempt to retrieve the metadata event from the local cache - const cachedRelayListMetadataEvent = - await localCache.getUserRelayListMetadata(hexKey) - - // Check if the cached event is not older than one week - if ( - cachedRelayListMetadataEvent && - !isOlderThanOneWeek(cachedRelayListMetadataEvent.cachedAt) - ) { - return cachedRelayListMetadataEvent.event - } - - return null - } catch (error) { - console.error(error) - return null - } -} - -/** - * Transforms a list of relay tags from a Nostr Event to a RelaySet. - * @param tags - */ -const getUserRelaySet = (tags: string[][]): RelaySet => { - return tags - .filter(isRelayTag) - .reduce(toRelaySet, getDefaultRelaySet()) -} - -const getDefaultRelaySet = (): RelaySet => ({ - read: [SIGIT_RELAY], - write: [SIGIT_RELAY] -}) - -const getDefaultRelayMap = (): RelayMap => ({ +export const getDefaultRelayMap = (): RelayMap => ({ [SIGIT_RELAY]: { write: true, read: true } }) - -const isOlderThanOneWeek = (cachedAt: number) => { - return Date.now() - cachedAt > ONE_WEEK_IN_MS -} - -const isOlderThanOneDay = (cachedAt: number) => { - return Date.now() - cachedAt > ONE_DAY_IN_MS -} - -const isRelayTag = (tag: string[]): boolean => tag[0] === 'r' -const addRelay = (list: string[], relay: string) => { - // Only add if the list doesn't already include the relay - if (!list.includes(relay)) list.push(relay) -} -const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => { - if (tag.length >= 3) { - const marker = tag[2] - - if (marker === READ_MARKER) { - addRelay(obj.read, tag[1]) - } else if (marker === WRITE_MARKER) { - addRelay(obj.write, tag[1]) - } - } - if (tag.length === 2) { - addRelay(obj.read, tag[1]) - addRelay(obj.write, tag[1]) - } - - return obj -} - -/** - * Provides relay map. - * @param npub - user's npub - * @returns - promise that resolves into relay map and a timestamp when it has been updated. - */ -const getRelayMap = async ( - npub: string -): Promise<{ map: RelayMap; mapUpdated?: number }> => { - // More info about this kind of event available https://github.com/nostr-protocol/nips/blob/master/65.md - const eventFilter: Filter = { - kinds: [kinds.RelayList], - authors: [npub] - } - - const event = await relayController - .fetchEvent(eventFilter, DEFAULT_LOOK_UP_RELAY_LIST) - .catch((err) => { - return Promise.reject(err) - }) - - if (event) { - // Handle founded 10002 event - const relaysMap: RelayMap = {} - - // 'r' stands for 'relay' - const relayTags = event.tags.filter((tag) => tag[0] === 'r') - - relayTags.forEach((tag) => { - const uri = tag[1] - const relayType = tag[2] - - // if 3rd element of relay tag is undefined, relay is WRITE and READ - relaysMap[uri] = { - write: relayType ? relayType === 'write' : true, - read: relayType ? relayType === 'read' : true - } - }) - - Object.keys(relaysMap).forEach((relayUrl) => - relayController.connectRelay(relayUrl) - ) - - getRelayInfo(Object.keys(relaysMap)) - - return Promise.resolve({ map: relaysMap, mapUpdated: event.created_at }) - } else { - return Promise.resolve({ map: getDefaultRelayMap() }) - } -} - /** * Publishes relay map. * @param relayMap - relay map. @@ -176,10 +44,11 @@ const getRelayMap = async ( * @param extraRelaysToPublish - optional relays to publish relay map. * @returns - promise that resolves into a string representing publishing result. */ -const publishRelayMap = async ( +export const publishRelayMap = async ( relayMap: RelayMap, npub: string, - extraRelaysToPublish?: string[] + ndk: NDK, + publish: (event: NDKEvent) => Promise ): Promise => { const timestamp = unixNow() const relayURIs = Object.keys(relayMap) @@ -208,21 +77,8 @@ const publishRelayMap = async ( const nostrController = NostrController.getInstance() const signedEvent = await nostrController.signEvent(newRelayMapEvent) - let relaysToPublish = relayURIs - - // Add extra relays if provided - if (extraRelaysToPublish) { - relaysToPublish = [...relaysToPublish, ...extraRelaysToPublish] - } - - // If relay map is empty, use most popular relay URIs - if (!relaysToPublish.length) { - relaysToPublish = DEFAULT_LOOK_UP_RELAY_LIST - } - const publishResult = await relayController.publish( - signedEvent, - relaysToPublish - ) + const ndkEvent = new NDKEvent(ndk, signedEvent) + const publishResult = await publish(ndkEvent) if (publishResult && publishResult.length) { return Promise.resolve( @@ -232,15 +88,3 @@ const publishRelayMap = async ( return Promise.reject('Publishing updated relay map was unsuccessful.') } - -export { - findRelayListAndUpdateCache, - findRelayListInCache, - getDefaultRelayMap, - getDefaultRelaySet, - getRelayMap, - getUserRelaySet, - isOlderThanOneDay, - isOlderThanOneWeek, - publishRelayMap -} diff --git a/src/utils/retry.ts b/src/utils/retry.ts new file mode 100644 index 0000000..b945e92 --- /dev/null +++ b/src/utils/retry.ts @@ -0,0 +1,25 @@ +export const retryAll = async ( + promises: (() => Promise)[], + retries: number = 3, + delay: number = 1000 +) => { + const wrappedPromises = promises.map((fn) => retry(fn, retries, delay)) + return Promise.allSettled(wrappedPromises) +} + +export const retry = async ( + fn: () => Promise, + retries: number = 3, + delay: number = 1000 +): Promise => { + try { + return await fn() + } catch (err) { + if (retries === 0) { + return Promise.reject(err) + } + return new Promise((resolve) => + setTimeout(() => resolve(retry(fn, retries - 1)), delay) + ) + } +} diff --git a/src/utils/sign.ts b/src/utils/sign.ts index ff67e44..dc3410c 100644 --- a/src/utils/sign.ts +++ b/src/utils/sign.ts @@ -1,46 +1,11 @@ -import { Event } from 'nostr-tools' -import { Meta } from '../types' - -/** - * This function returns the signature of last signer - * It will be used in the content of export signature's signedEvent - */ -const getLastSignersSig = ( - meta: Meta, - signers: `npub1${string}`[] -): string | null => { - // if there're no signers then use creator's signature - if (signers.length === 0) { - try { - const createSignatureEvent: Event = JSON.parse(meta.createSignature) - return createSignatureEvent.sig - } catch (error) { - return null - } - } - - // get last signer - const lastSigner = signers[signers.length - 1] - - // get the signature of last signer - try { - const lastSignatureEvent: Event = JSON.parse(meta.docSignatures[lastSigner]) - return lastSignatureEvent.sig - } catch (error) { - return null - } -} - /** * Checks if all signers have signed the sigit * @param signers - an array of npubs of all signers from the Sigit * @param signedBy - an array of npubs that have signed it already */ -const isFullySigned = ( +export const isFullySigned = ( signers: `npub1${string}`[], signedBy: `npub1${string}`[] ): boolean => { return signers.every((signer) => signedBy.includes(signer)) } - -export { getLastSignersSig, isFullySigned } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 11053b9..bcf2960 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -2,6 +2,18 @@ import { TimeoutError } from '../types/errors/TimeoutError.ts' import { CurrentUserFile } from '../types/file.ts' import { SigitFile } from './file.ts' +export const debounceCustom = void>( + fn: T, + delay: number +): ((...args: Parameters) => void) => { + let timerId: ReturnType + + return (...args: Parameters) => { + clearTimeout(timerId) + timerId = setTimeout(() => fn(...args), delay) + } +} + export const compareObjects = ( obj1: object | null | undefined, obj2: object | null | undefined @@ -119,3 +131,15 @@ export const settleAllFullfilfedPromises = async ( return acc }, []) } + +export const isPromiseFulfilled = ( + result: PromiseSettledResult +): result is PromiseFulfilledResult => { + return result.status === 'fulfilled' +} + +export const isPromiseRejected = ( + result: PromiseSettledResult +): result is PromiseRejectedResult => { + return result.status === 'rejected' +} diff --git a/src/utils/zip.ts b/src/utils/zip.ts index 577dd86..485c3ea 100644 --- a/src/utils/zip.ts +++ b/src/utils/zip.ts @@ -1,6 +1,12 @@ import JSZip from 'jszip' import { toast } from 'react-toastify' -import { InputFileFormat, OutputByType, OutputType } from '../types' +import { InputFileFormat, Meta, OutputByType, OutputType } from '../types' +import { NavigateOptions, To } from 'react-router-dom' +import { appPublicRoutes } from '../routes' +import { NostrController } from '../controllers' +import { decryptArrayBuffer } from './crypto' +import { hexToNpub, parseJson, SigitStatus, timeout } from '.' +import { SignerService } from '../services' /** * Read the content of a file within a zip archive. @@ -9,7 +15,7 @@ import { InputFileFormat, OutputByType, OutputType } from '../types' * @param outputType The type of output to return (e.g., 'string', 'arraybuffer', 'uint8array', etc.). * @returns A Promise resolving to the content of the file, or null if an error occurs. */ -const readContentOfZipEntry = async ( +export const readContentOfZipEntry = async ( zip: JSZip, filePath: string, outputType: T @@ -34,7 +40,7 @@ const readContentOfZipEntry = async ( }) } -const loadZip = async (data: InputFileFormat): Promise => { +export const loadZip = async (data: InputFileFormat): Promise => { try { return await JSZip.loadAsync(data) } catch (err) { @@ -46,4 +52,130 @@ const loadZip = async (data: InputFileFormat): Promise => { } } -export { readContentOfZipEntry, loadZip } +export const decrypt = async (file: File) => { + const nostrController = NostrController.getInstance() + + const zip = await loadZip(file) + if (!zip) return + + const keysFileContent = await readContentOfZipEntry( + zip, + 'keys.json', + 'string' + ) + + if (!keysFileContent) return null + + const parsedKeysJson = await parseJson<{ sender: string; keys: string[] }>( + keysFileContent + ).catch((err) => { + console.log(`Error parsing content of keys.json:`, err) + toast.error(err.message || `Error parsing content of keys.json`) + return null + }) + + if (!parsedKeysJson) return + + const encryptedArrayBuffer = await readContentOfZipEntry( + zip, + 'compressed.sigit', + 'arraybuffer' + ) + + if (!encryptedArrayBuffer) return + + const { keys, sender } = parsedKeysJson + + for (const key of keys) { + // decrypt the encryptionKey, with timeout (duration = 60 seconds) + const encryptionKey = await Promise.race([ + nostrController.nip04Decrypt(sender, key), + timeout(60000) + ]) + .then((res) => { + return res + }) + .catch((err) => { + console.log('err :>> ', err) + return null + }) + + // Return if encryption failed + if (!encryptionKey) continue + + const arrayBuffer = await decryptArrayBuffer( + encryptedArrayBuffer, + encryptionKey + ).catch((err) => { + console.log('err in decryption:>> ', err) + return null + }) + + if (arrayBuffer) return arrayBuffer + } + + return null +} + +type NavigateArgs = { to: To; options?: NavigateOptions } +export const navigateFromZip = async (file: File, pubkey: `npub1${string}`) => { + if (!file.name.endsWith('.sigit.zip')) { + toast.error(`Not a SiGit zip file: ${file.name}`) + } + + try { + let zip = await JSZip.loadAsync(file) + if (!zip) { + return null + } + + let arrayBuffer: ArrayBuffer | undefined + if ('keys.json' in zip.files) { + // Decrypt + const decryptedArrayBuffer = await decrypt(file).catch((err) => { + console.error(`error occurred in decryption`, err) + toast.error(err.message || `error occurred in decryption`) + }) + + if (decryptedArrayBuffer) { + // Replace the zip and continue processing + zip = await JSZip.loadAsync(decryptedArrayBuffer) + arrayBuffer = decryptedArrayBuffer + } + } + + if ('meta.json' in zip.files) { + // Check where we need to navigate + // Find Meta and process it for signer state + const metaContent = await readContentOfZipEntry( + zip, + 'meta.json', + 'string' + ) + if (metaContent) { + const meta = JSON.parse(metaContent) as Meta + const signerService = new SignerService(meta) + + const to = + signerService.getSignedStatus() === SigitStatus.Complete + ? appPublicRoutes.verify + : signerService.getNavigate(hexToNpub(pubkey)) + + return { + to, + options: { + state: { uploadedZip: arrayBuffer || file } + } + } as NavigateArgs + } + } + + return null + } catch (err) { + console.error('err in processing sigit zip file :>> ', err) + if (err instanceof Error) { + toast.error(err.message || 'An error occurred in loading zip file.') + } + return null + } +} diff --git a/vite.config.ts b/vite.config.ts index 3d09617..0d6be19 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,9 +1,16 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tsconfigPaths from 'vite-tsconfig-paths' +import { nodePolyfills } from 'vite-plugin-node-polyfills' export default defineConfig({ - plugins: [react(), tsconfigPaths()], + plugins: [ + react(), + tsconfigPaths(), + nodePolyfills({ + include: ['os'] + }) + ], build: { target: 'ES2022' }