diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000..48d5f81 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,10 @@ +--- +name: Custom issue template +about: Describe this issue template's purpose here. +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7df272..fb8f1e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: runs-on: [self-hosted, Linux, medium, ephemeral] strategy: matrix: - node: [ '14', '16' ] + node: [ '16' ] steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 diff --git a/.github/workflows/test.unit.yml b/.github/workflows/test.unit.yml new file mode 100644 index 0000000..25c95e7 --- /dev/null +++ b/.github/workflows/test.unit.yml @@ -0,0 +1,29 @@ +name: Test + +on: + pull_request: + branches: + - develop + push: + branches: + - develop + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node: [ '16' ] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - name: install dependencies + run: npm ci + - name: build + run: npm run build --if-present + - name: run unit test + run: npm run test:unit + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e8f55bc..f25fc6a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,9 +2,11 @@ name: Test on: pull_request: - branches: [ main ] + branches: + - main push: - branches: [ main ] + branches: + - main defaults: run: @@ -18,7 +20,7 @@ jobs: runs-on: [self-hosted, Linux, medium, ephemeral] strategy: matrix: - node: [ '14', '16' ] + node: [ '16' ] steps: - name: Checkout Code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 diff --git a/.gitignore b/.gitignore index 7d8d829..ce5013d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules/ /dist/ -.idea \ No newline at end of file +/demo/.env.json +.idea diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..4fd0219 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..838458f --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +/dist/ \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..246059f --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": false, + "printWidth": 120, + "tabWidth": 4, + "trailingComma": "es5" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4c64f7c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,126 @@ + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +# v1.0.0 + +## Removed + +* Generation of decentralized identifiers and creation of DID documents based on old [Hedera DID Method][did-method-spec] +* Creation of `identity networks` within `appnets`. +* Address book - a file on `Hedera File Service` that provides information about HCS topics and `appnet servers`. +* Creation and initialization of the `VC topic` - an HCS topic playing a role of verifiable credentials' registry. +* Creation (publishing), update, deletion and resolution of DID documents in `appnet identity networks`. +* Issuance, revocation and status verification of `Verifiable Credentials`. + +## Added + +* Generation of decentralized identifiers and creation of DID documents based on new [Hedera DID Method][did-method-spec] + Creation and initialization of the DID registration on `HCS Private Topic` +* Create, update, revoke, deletion, and resolution of DID documents based on [DID Document Core Properties][did-core-prop] `event/log messages` recorded on `HCS Topic` +* Transferring ownership of DID identifier and DID Document to another party. +* Publishing **DID Events Messages** to resolve and validate **DID Document** + +[did-core-prop]: https://w3c.github.io/did-core/#core-properties +[did-method-spec]: https://github.com/hashgraph/did-method + +### DID API's + +* Generate & Register + + ```js + ... + const registeredDid = await did.register(); + ``` + +* Resolve + + ```js + ... + const didDoc = await registeredDid.resolve(); + ``` + +* Change Ownership + + ```js + ... + await registeredDid.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: newOwnerDidPrivateKey, + }); + ``` + +* Create, Update and Revoke [DID Document Core Properties][did-core-prop] + * Service + + ```js + ... + await registeredDid.addService({ + id: serviceIdentifier + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + ... + await registeredDid.updateService({ + id: serviceIdentifier + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://test.com/did", + }); + ... + await registeredDid.revokeService({ + id: serviceIdentifier + "#service-1", + }); + ``` + +* Verification Method + + ```js + ... + await registeredDid.addVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: verificationMethodPublicKey, + }); + ... + await registeredDid.updateVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: updatedVerificationMethodPublicKey, + }); + ... + await registeredDid.revokeVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + }); + ``` + +* Verification Relationship + + ```js + ... + await registeredDid.addVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: verificationRelationshipPublicKey, + }); + ... + await registeredDid.updateVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: updatedVerificationRelationshipPublicKey, + }); + ... + await registeredDid.revokeVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + }); + ``` diff --git a/README.md b/README.md index 245e541..4faf871 100644 --- a/README.md +++ b/README.md @@ -1,140 +1,511 @@ # did-sdk-js -Support for the Hedera Hashgraph DID Method and Verifiable Credentials on the Hedera JavaScript/TypeScript SDK. -This repository contains the Javascript SDK for managing [DID Documents][did-core] & [Verifiable Credentials][vc-data-model] registry using the Hedera Consensus Service. +Support for the [Hedera Hashgraph DID Method](https://github.com/hashgraph/did-method) on the [Hedera JavaScript/TypeScript SDK](https://github.com/hashgraph/hedera-sdk-js). -did-sdk-js based on [did-sdk-java](https://github.com/hashgraph/did-sdk-java), so both of them contain similar methods and classes. +This repository contains the Javascript SDK for managing [DID Documents][did-core] using the Hedera Consensus Service. ## Overview -Identity networks are set of artifacts on Hedera Consensus Service that allow applications to share common channels to publish and resolve DID documents, issue verifiable credentials and control their validity status. These artifacts include: - -- address book - a file on Hedera File Service that provides information about HCS topics and appnet servers, -- DID topic - an HCS topic intended for publishing DID documents, -- and VC topic - an HCS topic playing a role of verifiable credentials registry. +Hedera Consensus Service (HCS) allows applications to share common channels to publish and resolve immutable and verifiable messages. These messages are submitted to Topic. SDK creates and uses **Private DID Topic** on HCS for publishing **DID Events Messages** to resolve and validate **DID Document**. This SDK is designed to simplify : -- creation of identity networks within appnets, that is: creation and initialization of the artifacts mentioned above, -- generation of decentralized identifiers for [Hedera DID Method][did-method-spec] and creation of their basic DID documents, -- creation (publishing), update, deletion and resolution of DID documents in appnet identity networks, -- issuance, revocation and status verification of [Verifiable Credentials][vc-data-model]. +- Creation and initialization of the DID registration on **HCS Restricted Topic**, +- Generation of decentralized identifiers for [Hedera DID Method][did-method-spec] and creation of DID documents, +- Create, update, revoke, deletion, and resolution of DID documents based on [DID Document Core Properties][did-core-prop] event/log messages recorded on **HCS Topic** +- Transferring ownership of DID identifier and DID Document to another party. -The SDK does not impose any particular way of how the DID or verifiable credential documents are constructed. Each appnet creators can choose their best way of creating those documents and as long as these are valid JSON-LD files adhering to W3C standards, they will be handled by the SDK. +The SDK adheres to W3C standards to produce valid hedera:did and resolve it to DID Document. SDK also provides API to create, update, revoke and delete different DID Events Messages that represent different properties of DID documents. ## Usage -``` + +```sh npm install --save @hashgraph/did-sdk-js ``` -## Example: +## Setup Hedera Portal Account -### Identity Network -``` -const client = ... // Client - -const identityNetwork = new HcsIdentityNetworkBuilder() - .setNetwork("testnet") - .setAppnetName("MyIdentityAppnet") - .addAppnetDidServer("https://appnet-did-server-url:port/path-to-did-api") - .setPublicKey(publicKey) - .setMaxTransactionFee(new Hbar(2)) - .setDidTopicMemo("MyIdentityAppnet DID topic") - .setVCTopicMemo("MyIdentityAppnet VC topic") - .execute(client); -``` +- Register hedera portal Testnet account +- Login to portal +- Obtain accountId & privateKey string value. -### DID Generation -From already instantiated network: -``` -const identityNetwork = ...; //HcsIdentityNetwork -// From a given DID root key: -const didRootKey = ...; //PrivateKey -const hcsDid = identityNetwork.generateDid(didRootKey.publicKey, false); +```json +"operator": { + "accountId": "0.0.xxxx", + "publicKey": "...", + "privateKey": "302.." +} ``` -or: -``` -// Without having a DID root key - it will be generated automatically: -// Here we decided to add DID topic ID parameter `tid` to the DID. -const hcsDidWithDidRootKey = identityNetwork.generateDid(true); -const didRootKeyPrivateKey = hcsDidWithDidRootKey.getPrivateDidRootKey().get(); -``` -or by directly constructing HcsDid object: -``` -const didRootKey = HcsDid.generateDidRootKey(); -const addressBookFileId = FileId.fromString(""); -const hcsDid = new HcsDid(HederaNetwork.TESTNET, didRootKey.publicKey, addressBookFileId); +- Following examples use accountId as `OPERATOR_ID` and privateKey string value as `OPERATOR_KEY` to submit DID Event Messages to HCS. + +## Examples + +Sample demo step by step javascript example are available at [Demo Folder][demo-location]. Make sure to add appropriate `testnet` account details in `.env.json` + +- OPERATOR_ID=0.0.xxxx +- OPERATOR_KEY=302... + +After running first step of the demo flow use printed out values to complete the `.env.json` configuration file. + +- DID_IDENTIFIER=did:hedera:testnet:..._0.0.xxx +- DID_PRIVATE_KEY=302... + +That's it! You are set to execute other demo flows. + +## DID Generation & Registration + +```javascript +const OPERATOR_ID=0.0.xxxx; +const OPERATOR_KEY=302...; + +/** +* Client setup +*/ +const client = Client.forTestnet(); +client.setOperator(OPERATOR_ID, OPERATOR_KEY); + +/** +* Build DID instance +*/ +const didPrivateKey = PrivateKey.generate(); +const did = new HcsDid({ privateKey: didPrivateKey, client: client }); +const registeredDid = await did.register(); + +console.log("\n"); +console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); +console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); +console.log(registeredDid.getIdentifier()); ``` -Existing Hedera DID strings can be parsed into HcsDid object by calling fromString method: + +## DID Resolve + +```javascript +/** +* Setup +*/ +const client = Client.forTestnet(); + +/** +* CHANGE IT. use values from step 1: registered DID console output +*/ +const existingDIDIdentifier = "did:hedera:testnet:zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo_0.0.29656526"; + +/** +* Build DID instance +*/ +const did = new HcsDid({ identifier: existingDIDIdentifier, client: client }); + +/** +* Resolve DID +*/ +console.log("generating did doc"); +const didDoc = await did.resolve(); +console.log(didDoc.toJsonTree()); + +console.log("\n"); +console.log("==================================================="); +console.log("DragonGlass Explorer:"); +console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); +console.log("\n"); ``` -const didString = "did:hedera:testnet:7c38oC4ytrYDGCqsaZ1AXt7ZPQ8etzfwaxoKjfJNzfoc;hedera:testnet:fid=0.0.1"; -const did = HcsDid.fromString(didString); + +## Change Ownership + +### Change DID Ownership, works under the following **assumption** + +- Current DID owner **transfers** registered DID PrivateKey to new owner using **secure channel**. +- New owner **performs change did owner operation** with existing owner registered DID PrivateKey and new owners PrivateKey. + +### Change DID Ownership performs following tasks + +- It **transfers** the ownership of **DIDDocument** and **HCS Topic**. +- It **updates** Topic **AdminKey** and **SubmitKey** by signing updateTopicTransaction with **both** existing owner PrivateKey and new owner PrivateKey +- It also **submits** Update DIDOwner **Event** to **HCS Topic** with new owner PublicKey. - of course singed by new owner PrivateKey +- Eventually, when **DID Document** get **resolved**, Update DIDOwner **Event** new owner PublicKey translates to DID Document **controller/#did-root-key** + +```javascript +const OPERATOR_ID=0.0.xxxx; +const PRIVATE_KEY_STR=302...; + +/** +* Setup +*/ +const client = Client.forTestnet(); +client.setOperator(OPERATOR_ID, OPERATOR_KEY); + +/** +* CHANGE IT. use values from step 1: registered DID console output +*/ +const existingOwnerDIDPrivateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" +); +const existingDIDIdentifier = "did:hedera:testnet:zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo_0.0.29656526"; + +/** +* Build DID instance +*/ +const registeredDid = new HcsDid({ + identifier: existingDIDIdentifier, + privateKey: existingOwnerDIDPrivateKey, + client: client, +}); + +/** +* New Owner PrivateKey +*/ +const newOwnerDidPrivateKey = PrivateKey.generate(); +const newOwnerIdentifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + +/** +* Change ownership +*/ +await registeredDid.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: newOwnerDidPrivateKey, +}); + +console.log("generating did doc"); +const didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +console.log("\n"); +console.log("New Owner Information"); +console.log(`DID PRIVATE KEY: ${newOwnerDidPrivateKey.toString()}`); +console.log(`DID PUBLIC KEY: ${newOwnerDidPrivateKey.publicKey.toString()}`); + +console.log("\n"); +console.log("==================================================="); +console.log("DragonGlass Explorer:"); +console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); +console.log("\n"); ``` -### Transaction +## Create, Update and Revoke [DID Document Core Properties][did-core-prop] + +## Service + +```javascript +const OPERATOR_ID=0.0.xxxx; +const PRIVATE_KEY_STR=302...; + +/** +* Setup +*/ +const client = Client.forTestnet(); +client.setOperator(OPERATOR_ID, OPERATOR_KEY); + +/** +* CHANGE IT. use values from did registration step +*/ +const didPrivateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" +); +const existingDIDIdentifier = "did:hedera:testnet:zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo_0.0.29656526"; + +/** +* Build DID instance +*/ +const registeredDid = new HcsDid({ identifier: existingDIDIdentifier, privateKey: didPrivateKey, client: client }); + +/** +* Add Service +*/ +const serviceIdentifier = "did:hedera:testnet:z6MkubW6fwkWSA97RbKs17MtLgWGHBtShQygUc5SeHueFCaG_0.0.29656231"; + +await registeredDid.addService({ + id: serviceIdentifier + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", +}); + +console.log("\n"); +console.log("Added"); +let didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +/** +* Update Service +* ID must be same as ADD Service Event to update it +*/ +await registeredDid.updateService({ + id: serviceIdentifier + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://test.com/did", +}); + +console.log("\n"); +console.log("Updated"); +didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +/** +* Revoke Service +*/ +await registeredDid.revokeService({ + id: serviceIdentifier + "#service-1", +}); + +console.log("\n"); +console.log("Revoked"); +didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +console.log("\n"); +console.log("Registered DID Information"); +console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); +console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); +console.log(registeredDid.getIdentifier()); + ``` -const client = ...; //Client -const identityNetwork = ...; //HcsIdentityNetwork - -const didRootKey = ...; //PrivateKey -const hcsDid = ...; //HcsDid - -const didDocument = hcsDid.generateDidDocument().toJson(); - -// Build and execute transaction -await identityNetwork.createDidTransaction(DidMethodOperation.CREATE) - // Provide DID document as JSON string - .setDidDocument(didDocument) - // Sign it with DID root key - .signMessage(doc => didRootKey.sign(doc)) - // Configure ConsensusMessageSubmitTransaction, build it and sign if required by DID topic - .buildAndSignTransaction(tx => tx.setMaxTransactionFee(new Hbar(2))) - // Define callback function when consensus was reached and DID document came back from mirror node - .onMessageConfirmed(msg => { - //DID document published! - }) - // Execute transaction - .execute(client); + +## Verification Method + +```javascript +const OPERATOR_ID=0.0.xxxx; +const PRIVATE_KEY_STR=302...; + +/** +* Setup +*/ +const client = Client.forTestnet(); +client.setOperator(OPERATOR_ID, OPERATOR_KEY); + +/** +* CHANGE IT. use values from step 1: registered DID console output +*/ +const didPrivateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" +); +const existingDIDIdentifier = "did:hedera:testnet:zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo_0.0.29656526"; + +/** +* Build DID instance +*/ +const registeredDid = new HcsDid({ identifier: existingDIDIdentifier, privateKey: didPrivateKey, client: client }); + +const verificationMethodIdentifier = + "did:hedera:testnet:z6Mkkcn1EDXc5vzpmvnQeCKpEswyrnQG7qq59k92gFRm1EGk_0.0.29617801"; +const verificationMethodPublicKey = HcsDid.stringToPublicKey("z6Mkkcn1EDXc5vzpmvnQeCKpEswyrnQG7qq59k92gFRm1EGk"); +const updatedVerificationMethodPublicKey = HcsDid.stringToPublicKey( + "z6MkhHbhBBLdKGiGnHPvrrH9GL7rgw6egpZiLgvQ9n7pHt1P" +); + +/** +* Add Verification Method +*/ +await registeredDid.addVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: verificationMethodPublicKey, +}); + +console.log("\n"); +console.log("Added"); +let didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +/** + * Update Verification Method +* ID must be same as ADD Verification Method Event to update it +*/ +await registeredDid.updateVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: updatedVerificationMethodPublicKey, +}); +console.log("\n"); +console.log("Updated"); +didDoc = await registeredDid.resolve(); + +console.log(didDoc.toJsonTree()); + +/** +* Revoke Verification Method +*/ +await registeredDid.revokeVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", +}); +console.log("\n"); +console.log("Revoked"); +didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +console.log("\n"); +console.log("Registered DID Information"); +console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); +console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); +console.log(registeredDid.getIdentifier()); ``` [did-method-spec]: https://github.com/hashgraph/did-method [did-core]: https://www.w3.org/TR/did-core/ -[vc-data-model]: https://www.w3.org/TR/vc-data-model/ +[demo-location]: https://github.com/Meeco/did-sdk-js/tree/develop/demo +[did-core-prop]: https://w3c.github.io/did-core/#core-properties -## Development +## Verification RelationShip - Authentication + +```javascript +const OPERATOR_ID=0.0.xxxx; +const PRIVATE_KEY_STR=302...; +/** +* Setup +*/ +const client = Client.forTestnet(); +client.setOperator(OPERATOR_ID, OPERATOR_KEY); + +/** +* CHANGE IT. use values from step 1: registered DID console output +*/ +const didPrivateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" +); +const existingDIDIdentifier = "did:hedera:testnet:zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo_0.0.29656526"; + +/** +* Build DID instance +*/ +const registeredDid = new HcsDid({ identifier: existingDIDIdentifier, privateKey: didPrivateKey, client: client }); + +const verificationRelationshipIdentifier = + "did:hedera:testnet:z6Mkkcn1EDXc5vzpmvnQeCKpEswyrnQG7qq59k92gFRm1EGk_0.0.29617801"; +const verificationRelationshipPublicKey = HcsDid.stringToPublicKey( + "z6Mkkcn1EDXc5vzpmvnQeCKpEswyrnQG7qq59k92gFRm1EGk" +); +const updatedVerificationRelationshipPublicKey = HcsDid.stringToPublicKey( + "z6MkhHbhBBLdKGiGnHPvrrH9GL7rgw6egpZiLgvQ9n7pHt1P" +); +const verificationRelationshipType = "authentication"; + +/** +* Add VerificationRelationship - authentication +*/ +await registeredDid.addVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: verificationRelationshipPublicKey, +}); + +console.log("\n"); +console.log("Added"); +let didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +/** + * Update VerificationRelationship - authentication +* ID & relationshipType must be same as ADD Service Event to update it +*/ +await registeredDid.updateVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: updatedVerificationRelationshipPublicKey, +}); + +console.log("\n"); +console.log("Updated"); +didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +/** + * Revoke Service +* ID & relationshipType must be same as ADD Service Event to update it +*/ +await registeredDid.revokeVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, +}); + +console.log("\n"); +console.log("Revoked"); +didDoc = await registeredDid.resolve(); +console.log(didDoc.toJsonTree()); + +console.log("\n"); +console.log("Registered DID Information"); +console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); +console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); +console.log(registeredDid.getIdentifier()); ``` -git clone git@github.com:hashgraph/did-sdk-js.git + +## Delete DID Document + +```javascript +const OPERATOR_ID=0.0.xxxx; +const PRIVATE_KEY_STR=302...; + +/** +* Client setup +*/ +const privateKey = PrivateKey.fromString(OPERATOR_KEY); +const client = Client.forTestnet(); +client.setOperator(OPERATOR_ID, privateKey); + +/** +* CHANGE IT. use values from step 1: registered DID console output +*/ +const didPrivateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" +); +const existingDIDIdentifier = "did:hedera:testnet:zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo_0.0.29656526"; + +/** +* Build DID instance +*/ +const did = new HcsDid({ identifier: existingDIDIdentifier, privateKey: didPrivateKey, client: client }); + +/** +* Delete DID +*/ +did.delete(); ``` -First you need install dependencies and build project +## Development + +```sh +git clone git@github.com:hashgraph/did-sdk-js.git ``` + +First, you need to install dependencies and build the project + +```sh npm install ``` + Run build in dev mode (with sourcemap generation and following changes) -``` + +```sh npm run build:dev ``` ## Tests -For run tests you need to create and fill ```test/variables.js``` file before. There is ```test/variables.js.sample``` file as example. -Update the following environment variables with your `testnet` account details +Run Unit Tests -* OPERATOR_ID=0.0.xxxx -* OPERATOR_KEY=302... +```sh +npm run test:unit +``` -You may also edit the following to use a different network (ensure your OPERATOR_ID and OPERATOR_KEY are valid) +Run Integration Test -* NETWORK=testnet (can be `testnet`, `previewnet` or `mainnet`) -* MIRROR_PROVIDER=hedera (can be `hedera` or `kabuto` (note `kabuto` not available on `previewnet`)) +Open jest.setup.js file and update the following environment variables with your `testnet` account details -Run tests +```js +process.env.OPERATOR_ID = "0.0.xxxxxx"; +process.env.OPERATOR_KEY = "302e02..."; ``` -npm run test + +```sh +npm run test:integration ``` ## References + - - - diff --git a/demo/.env.json.example b/demo/.env.json.example new file mode 100644 index 0000000..9dc6158 --- /dev/null +++ b/demo/.env.json.example @@ -0,0 +1,28 @@ +COMMENT_0: Account that is going to pay for the demo +OPERATOR_ID: "xxx" + +COMMENT_1: Account private key +OPERATOR_KEY: "302e..." + +COMMENT_2: ======================================================================================================== +COMMENT_3: IMPORTANT: after running step 1 please put below generated DID identifier and private key values. +COMMENT_4: Then later steps can be executed. +COMMENT_5: ======================================================================================================== + +COMMENT_6: DID document identifier +DID_IDENTIFIER: "did:hedera:testnet:..." + +COMMENT_7: DID private key +DID_PRIVATE_KEY: "302e..." + +EXAMPLE JSON CONFIG + +{ + "OPERATOR_ID": "0.0.12345", + + "OPERATOR_KEY": "302e...", + + "DID_IDENTIFIER": "did:hedera:tes...", + + "DID_PRIVATE_KEY": "302e..." +} \ No newline at end of file diff --git a/demo/1_generate_register_did.js b/demo/1_generate_register_did.js new file mode 100644 index 0000000..eda75b9 --- /dev/null +++ b/demo/1_generate_register_did.js @@ -0,0 +1,25 @@ +const { PrivateKey, Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { OPERATOR_ID, OPERATOR_KEY } = require("./.env.json"); + +async function main() { + /** + * Client setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /** + * Build DID instance + */ + const didPrivateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey: didPrivateKey, client: client }); + const registeredDid = await did.register(); + + console.log("\n"); + console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); + console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); + console.log(registeredDid.getIdentifier()); +} + +main(); diff --git a/demo/2_add_update_revoke_service.js b/demo/2_add_update_revoke_service.js new file mode 100644 index 0000000..0847b7a --- /dev/null +++ b/demo/2_add_update_revoke_service.js @@ -0,0 +1,69 @@ +const { PrivateKey, Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { OPERATOR_ID, OPERATOR_KEY, DID_IDENTIFIER, DID_PRIVATE_KEY } = require("./.env.json"); + +async function main() { + /** + * Setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + const didPrivateKey = PrivateKey.fromString(DID_PRIVATE_KEY); + + /** + * Build DID instance + */ + const registeredDid = new HcsDid({ identifier: DID_IDENTIFIER, privateKey: didPrivateKey, client: client }); + + /** + * Add Service + */ + const serviceIdentifier = "did:hedera:testnet:z6MkubW6fwkWSA97RbKs17MtLgWGHBtShQygUc5SeHueFCaG_0.0.29656231"; + + await registeredDid.addService({ + id: serviceIdentifier + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + + console.log("\n"); + console.log("Added"); + let didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + /** + * Update Service + * ID must be same as ADD Service Event to update it + */ + await registeredDid.updateService({ + id: serviceIdentifier + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://test.com/did", + }); + + console.log("\n"); + console.log("Updated"); + didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + /** + * Revoke Service + */ + await registeredDid.revokeService({ + id: serviceIdentifier + "#service-1", + }); + + console.log("\n"); + console.log("Revoked"); + didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + console.log("\n"); + console.log("Registered DID Information"); + console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); + console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); + console.log(registeredDid.getIdentifier()); +} + +main(); diff --git a/demo/2_add_update_revoke_verification_method.js b/demo/2_add_update_revoke_verification_method.js new file mode 100644 index 0000000..74dcf34 --- /dev/null +++ b/demo/2_add_update_revoke_verification_method.js @@ -0,0 +1,75 @@ +const { PrivateKey, Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { OPERATOR_ID, OPERATOR_KEY, DID_IDENTIFIER, DID_PRIVATE_KEY } = require("./.env.json"); + +async function main() { + /** + * Setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + const didPrivateKey = PrivateKey.fromString(DID_PRIVATE_KEY); + + /** + * Build DID instance + */ + const registeredDid = new HcsDid({ identifier: DID_IDENTIFIER, privateKey: didPrivateKey, client: client }); + + const verificationMethodIdentifier = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801"; + const verificationMethodPublicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + const updatedVerificationMethodPublicKey = HcsDid.stringToPublicKey( + "zAvU2AEh8ybRqNwHAM3CjbkjYaYHpt9oA1uugW9EVTg6P" + ); + + /** + * Add Verification Method + */ + await registeredDid.addVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: verificationMethodPublicKey, + }); + + console.log("\n"); + console.log("Added"); + let didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + /** + * Update Verification Method + * ID must be same as ADD Verification Method Event to update it + */ + await registeredDid.updateVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: updatedVerificationMethodPublicKey, + }); + console.log("\n"); + console.log("Updated"); + didDoc = await registeredDid.resolve(); + + console.log(didDoc.toJsonTree()); + + /** + * Revoke Verification Method + */ + await registeredDid.revokeVerificationMethod({ + id: verificationMethodIdentifier + "#key-1", + }); + console.log("\n"); + console.log("Revoked"); + didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + console.log("\n"); + console.log("Registered DID Information"); + console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); + console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); + console.log(registeredDid.getIdentifier()); +} + +main(); diff --git a/demo/2_add_update_revoke_verification_relationship.js b/demo/2_add_update_revoke_verification_relationship.js new file mode 100644 index 0000000..654e3a6 --- /dev/null +++ b/demo/2_add_update_revoke_verification_relationship.js @@ -0,0 +1,81 @@ +const { PrivateKey, Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { OPERATOR_ID, OPERATOR_KEY, DID_PRIVATE_KEY, DID_IDENTIFIER } = require("./.env.json"); + +async function main() { + /** + * Setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + const didPrivateKey = PrivateKey.fromString(DID_PRIVATE_KEY); + + /** + * Build DID instance + */ + const registeredDid = new HcsDid({ identifier: DID_IDENTIFIER, privateKey: didPrivateKey, client: client }); + + const verificationRelationshipIdentifier = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801"; + const verificationRelationshipPublicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + const updatedVerificationRelationshipPublicKey = HcsDid.stringToPublicKey( + "zAvU2AEh8ybRqNwHAM3CjbkjYaYHpt9oA1uugW9EVTg6P" + ); + const verificationRelationshipType = "authentication"; + + /** + * Add VerificationRelationship - authentication + */ + await registeredDid.addVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: verificationRelationshipPublicKey, + }); + + console.log("\n"); + console.log("Added"); + let didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + /** + * Update VerificationRelationship - authentication + * ID & relationshipType must be same as ADD Service Event to update it + */ + await registeredDid.updateVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + type: "Ed25519VerificationKey2018", + controller: registeredDid.getIdentifier(), + publicKey: updatedVerificationRelationshipPublicKey, + }); + + console.log("\n"); + console.log("Updated"); + didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + /** + * Revoke Service + * ID & relationshipType must be same as ADD Service Event to update it + */ + await registeredDid.revokeVerificationRelationship({ + id: verificationRelationshipIdentifier + "#key-1", + relationshipType: verificationRelationshipType, + }); + + console.log("\n"); + console.log("Revoked"); + didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + console.log("\n"); + console.log("Registered DID Information"); + console.log(`DID PRIVATE KEY: ${didPrivateKey.toString()}`); + console.log(`DID PUBLIC KEY: ${didPrivateKey.publicKey.toString()}`); + console.log(registeredDid.getIdentifier()); +} + +main(); diff --git a/demo/3_read_did_messages.js b/demo/3_read_did_messages.js new file mode 100644 index 0000000..288540b --- /dev/null +++ b/demo/3_read_did_messages.js @@ -0,0 +1,43 @@ +const { Client, Timestamp } = require("@hashgraph/sdk"); +const { HcsDid, HcsDidEventMessageResolver } = require("../dist"); +const { DID_IDENTIFIER } = require("./.env.json"); + +async function main() { + /** + * Setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + + /** + * Build DID instance + */ + const did = new HcsDid({ identifier: DID_IDENTIFIER }); + + /** + * Read DID resolver setup + */ + new HcsDidEventMessageResolver(did.getTopicId()) + .setTimeout(HcsDid.READ_TOPIC_MESSAGES_TIMEOUT) + .whenFinished((envelopes) => { + envelopes.forEach((envelope) => { + const msg = envelope.open(); + + console.log("\n"); + console.log("==================================================="); + console.log("\n"); + console.log("Message:"); + console.log(msg.toJsonTree()); + console.log("\n"); + console.log("Event:"); + console.log(msg.event.toJsonTree()); + }); + console.log("\n"); + console.log("==================================================="); + console.log("DragonGlass Explorer:"); + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + console.log("\n"); + }) + .execute(client); +} + +main(); diff --git a/demo/4_resolve_did.js b/demo/4_resolve_did.js new file mode 100644 index 0000000..388aebb --- /dev/null +++ b/demo/4_resolve_did.js @@ -0,0 +1,31 @@ +const { Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { DID_IDENTIFIER } = require("./.env.json"); + +async function main() { + /** + * Setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + + /** + * Build DID instance + */ + const did = new HcsDid({ identifier: DID_IDENTIFIER, client: client }); + + /** + * Resolve DID + */ + + console.log("generating did doc"); + const didDoc = await did.resolve(); + console.log(didDoc.toJsonTree()); + + console.log("\n"); + console.log("==================================================="); + console.log("DragonGlass Explorer:"); + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + console.log("\n"); +} + +main(); diff --git a/demo/5_change_did_ownership.js b/demo/5_change_did_ownership.js new file mode 100644 index 0000000..cd56fc1 --- /dev/null +++ b/demo/5_change_did_ownership.js @@ -0,0 +1,71 @@ +const { PrivateKey, Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { OPERATOR_ID, OPERATOR_KEY, DID_IDENTIFIER, DID_PRIVATE_KEY } = require("./.env.json"); + +async function main() { + /** + * + * Change DID Ownership, works under the following assumption. + * + * Current DID Owner transfers registered DID PrivateKey to New Owner using secure channel. + * New Owner performs change did owner operation with existing registered DID PrivateKey and new owners PrivateKey. + * + */ + + /** + * + * Change DID Ownership performs following tasks + * + * It transfers the ownership of DIDDocument and HCS Topic + * It updates Topic AdminKey and SubmitKey by signing updateTopicTransaction with both existing owner PrivateKey and new owner PrivateKey + * It also submits Update DIDOwner Event to HCS topic with new owner PublicKey. - of course singed by new owner PrivateKey + * Eventually, when DID Document get resolved, Update DIDOwner Event translates to DID Document controller/#did-root-key + */ + + /** + * Setup + */ + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + const existingOwnerDIDPrivateKey = PrivateKey.fromString(DID_PRIVATE_KEY); + + /** + * Build DID instance + */ + const registeredDid = new HcsDid({ + identifier: DID_IDENTIFIER, + privateKey: existingOwnerDIDPrivateKey, + client: client, + }); + + /** + * New Owner PrivateKey + */ + const newOwnerDidPrivateKey = PrivateKey.generate(); + const newOwnerIdentifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + + /** + * Change ownership + */ + await registeredDid.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: newOwnerDidPrivateKey, + }); + + console.log("generating did doc"); + const didDoc = await registeredDid.resolve(); + console.log(didDoc.toJsonTree()); + + console.log("\n"); + console.log("New Owner Information"); + console.log(`DID PRIVATE KEY: ${newOwnerDidPrivateKey.toString()}`); + console.log(`DID PUBLIC KEY: ${newOwnerDidPrivateKey.publicKey.toString()}`); + + console.log("\n"); + console.log("==================================================="); + console.log("DragonGlass Explorer:"); + console.log(`https://testnet.dragonglass.me/hedera/topics/${registeredDid.getTopicId().toString()}`); + console.log("\n"); +} +main(); diff --git a/demo/6_delete_did_document.js b/demo/6_delete_did_document.js new file mode 100644 index 0000000..f8b28ab --- /dev/null +++ b/demo/6_delete_did_document.js @@ -0,0 +1,26 @@ +const { PrivateKey, Client } = require("@hashgraph/sdk"); +const { HcsDid } = require("../dist"); +const { OPERATOR_ID, OPERATOR_KEY, DID_IDENTIFIER, DID_PRIVATE_KEY } = require("./.env.json"); + +async function main() { + /** + * Client setup + */ + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(OPERATOR_ID, privateKey); + + const didPrivateKey = PrivateKey.fromString(DID_PRIVATE_KEY); + + /** + * Build DID instance + */ + const did = new HcsDid({ identifier: DID_IDENTIFIER, privateKey: didPrivateKey, client: client }); + + /** + * Delete DID + */ + did.delete(); +} + +main(); diff --git a/documentation/diagrams/did-add-attribute.mmd b/documentation/diagrams/did-add-attribute.mmd new file mode 100644 index 0000000..0d68657 --- /dev/null +++ b/documentation/diagrams/did-add-attribute.mmd @@ -0,0 +1,19 @@ +sequenceDiagram +Title: Add DID attribute + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HCS as Hedera Consensus Service + participant HMN as Hedera Mirror Node + + +alt Add DID attribute + +App ->> SDK: Send Add attribute DID request with identifier and PK +SDK ->> HSDK: Build Client (Set account that will pay for transaction) +SDK ->> HCS: Send Add DID attribute Event message +HCS ->> HMN: Propagate Message
to Topic +SDK ->> HSDK: Subscribe to the topic and
wait till message is successfully submited +SDK -->> App: Send DID Identifier +end \ No newline at end of file diff --git a/documentation/diagrams/did-delegate.mmd b/documentation/diagrams/did-delegate.mmd new file mode 100644 index 0000000..b978716 --- /dev/null +++ b/documentation/diagrams/did-delegate.mmd @@ -0,0 +1,24 @@ +sequenceDiagram +Title: DID Delegate + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HCS as Hedera Consensus Service + participant HMN as Hedera Mirror Node + + +alt Delegate a DID + +App ->> HSDK: Build Client (Set account that will pay for transaction) +App ->> HSDK: Generate New Owner DID Private Key (DPK) +App ->> SDK: Register DID with DPK +SDK ->> SDK: Build did identifier with topic id +SDK ->> SDK: Create DID owner Event message
with identifier +SDK ->> HSDK: Build DID owner Event message Transaction
signed with DPK +SDK ->> HSDK: Execute above transaction with Client +HSDK ->> HCS: Submit message to Topic +HCS ->> HMN: Propagate Message
to Topic +SDK ->> HSDK: Subscribe to the topic and
wait till message is successfully submited +SDK -->> App: Send DID Identifier
e.g. (did:hedera:testnet:z6Mk.._0.0.2..) +end \ No newline at end of file diff --git a/documentation/diagrams/did-delete.mmd b/documentation/diagrams/did-delete.mmd new file mode 100644 index 0000000..01d487a --- /dev/null +++ b/documentation/diagrams/did-delete.mmd @@ -0,0 +1,19 @@ +sequenceDiagram +Title: Delete DID + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HCS as Hedera Consensus Service + participant HMN as Hedera Mirror Node + + +alt Delete DID + +App ->> SDK: Send Delete DID request with identifier and DID Private Key +SDK ->> HSDK: Build Client (Set account that will pay for transaction) +SDK ->> HCS: Send Delete DID Event message +HCS ->> HMN: Propagate Message
to Topic +SDK ->> HSDK: Subscribe to the topic and
wait till message is successfully submited +SDK -->> App: Send DID Identifier +end \ No newline at end of file diff --git a/documentation/diagrams/did-registration.mmd b/documentation/diagrams/did-registration.mmd new file mode 100644 index 0000000..0388f14 --- /dev/null +++ b/documentation/diagrams/did-registration.mmd @@ -0,0 +1,30 @@ +sequenceDiagram +Title: DID Registration + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HCS as Hedera Consensus Service + participant HMN as Hedera Mirror Node + + +alt Register a DID + +App ->> HSDK: Build Client (Set account that will pay for transaction) +App ->> HSDK: Generate DID Private Key (DPK) +App ->> SDK: Register DID with DPK +SDK ->> HSDK: Build Topic Create Transaction
By setting Transaction Fees
AdminKey, SubmitKey
signed by DPK +SDK ->> HSDK: Execute above transaction with Client
(responsible for transaction payment) +HSDK ->> HCS: Create Private Topic +HCS ->> HMN: Propagate Topic +SDK ->> HSDK: Request Receipt for Transaction +HSDK -->> SDK: Send receipt with Topic ID +SDK ->> SDK: Build did identifier with topic id +SDK ->> SDK: Create DID owner Event message
with identifier +SDK ->> HSDK: Build DID owner Event message Transaction
signed with DPK +SDK ->> HSDK: Execute above transaction with Client
(responsible for transaction payment) +HSDK ->> HCS: Submit message to Topic +HCS ->> HMN: Propagate Message
to Topic +SDK ->> HSDK: Subscribe to the topic and
wait till message is successfully submited +SDK -->> App: Send DID Identifier
e.g. (did:hedera:testnet:z6Mk.._0.0.2..) +end diff --git a/documentation/diagrams/did-resolve.mmd b/documentation/diagrams/did-resolve.mmd new file mode 100644 index 0000000..cf804dc --- /dev/null +++ b/documentation/diagrams/did-resolve.mmd @@ -0,0 +1,26 @@ +sequenceDiagram +Title: DID Resolve + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HMN as Hedera Mirror Node + + +alt Resolve a DID + +App ->> HSDK: Build Client (No Hedera account info needed) +App ->> SDK: Create HCS DID Object with
DID Identifier
e.g. (did:hedera:testnet:z6Mk.._0.0.2..) +App ->> SDK: Resolve a DID +SDK ->> SDK: Extract topic id from DID +SDK ->> HSDK: Subscribe to Topic +HSDK ->> HMN: Subscribe to Topic +HMN -->> HSDK: Receive all messages +HSDK -->> SDK: Receive all messages +SDK ->> SDK: Extract all Events from messages +SDK ->> SDK: Process events +SDK ->> SDK: Generate DID Document +SDK -->> App: Send DID Document +end + + diff --git a/documentation/diagrams/did-revoke-attribute.mmd b/documentation/diagrams/did-revoke-attribute.mmd new file mode 100644 index 0000000..3491c8c --- /dev/null +++ b/documentation/diagrams/did-revoke-attribute.mmd @@ -0,0 +1,19 @@ +sequenceDiagram +Title: Revoke DID attribute + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HCS as Hedera Consensus Service + participant HMN as Hedera Mirror Node + + +alt Revoke DID attribute + +App ->> SDK: Send Revoke attribute DID request with identifier and PK +SDK ->> HSDK: Build Client (Set account that will pay for transaction) +SDK ->> HCS: Send Revoke DID attribute Event message +HCS ->> HMN: Propagate Message
to Topic +SDK ->> HSDK: Subscribe to the topic and
wait till message is successfully submited +SDK -->> App: Send DID Identifier +end \ No newline at end of file diff --git a/documentation/diagrams/did-update-attribute.mmd b/documentation/diagrams/did-update-attribute.mmd new file mode 100644 index 0000000..1ee6667 --- /dev/null +++ b/documentation/diagrams/did-update-attribute.mmd @@ -0,0 +1,19 @@ +sequenceDiagram +Title: Update DID attribute + autonumber + participant App as Application + participant SDK as DID JS SDK + participant HSDK as Hashgraph JS SDK + participant HCS as Hedera Consensus Service + participant HMN as Hedera Mirror Node + + +alt Update DID attribute + +App ->> SDK: Send Update attribute DID request with identifier and PK +SDK ->> HSDK: Build Client (Set account that will pay for transaction) +SDK ->> HMN: Send Update DID attribute Event message +HCS ->> HMN: Propagate Message
to Topic +SDK ->> HSDK: Subscribe to the topic and
wait till message is successfully submited +SDK -->> App: Send DID Identifier +end \ No newline at end of file diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..7ed666a --- /dev/null +++ b/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", + setupFilesAfterEnv: ["./jest.setupAfterEnv.js"], + setupFiles: ["./jest.setup.js"], + modulePathIgnorePatterns: ["/dist/"], +}; diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..c013bfe --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,5 @@ +// process.env.OPERATOR_ID = "0.0.xxxxxx"; +// process.env.OPERATOR_KEY = +// "302e02..."; + +process.env.WAIT_BEFORE_RESOLVE_DID_FOR = 30000; diff --git a/jest.setupAfterEnv.js b/jest.setupAfterEnv.js new file mode 100644 index 0000000..5033304 --- /dev/null +++ b/jest.setupAfterEnv.js @@ -0,0 +1 @@ +jest.setTimeout(80000); diff --git a/package-lock.json b/package-lock.json index ec2de9c..f2982dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,4041 +1,11464 @@ { - "name": "@hashgraph/did-sdk-js", - "version": "0.1.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@hashgraph/did-sdk-js", - "version": "0.1.0", - "license": "Apache-2.0", - "dependencies": { - "@hashgraph/sdk": "^2.0.20", - "bs58": "^4.0.1", - "js-base64": "^3.6.1", - "moment": "^2.29.1" - }, - "devDependencies": { - "@types/node": "^16.7.7", - "chai": "^4.3.4", - "mocha": "^9.0.1", - "nodemon": "^2.0.7", - "typescript": "^4.3.2" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.7.tgz", - "integrity": "sha512-CKQVuwuSPh40tgOkR7c0ZisxYRiN05PcKPW72mQL5y++qd7CwBRoaJZvU5xfXnCJDFBmS3qZGQ71Frx6Ofo2XA==", - "dependencies": { - "@types/node": ">=12.12.47" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@hashgraph/cryptography": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.0.20.tgz", - "integrity": "sha512-rdKKnENJfs0gsqAtY+7nzpG9TQshtnf+F3/PdH8z+qdy4mo4RSULBMc55FkWWNZLnoA4/34wEW8kohjFEzsLRA==", - "dependencies": { - "@types/crypto-js": "^4.0.2", - "@types/utf8": "^3.0.0", - "bignumber.js": "^9.0.1", - "crypto-js": "^4.0.0", - "expo-crypto": "^9.2.0", - "expo-random": "^11.2.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "js-base64": "^3.6.1", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@hashgraph/proto": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-1.1.9.tgz", - "integrity": "sha512-BOY5LD8NCjFot0EFXla2ZX8Q7UE94ZDQoSKXK/XVwlLgcMNSArdIPfK4zy4EBvLZnWV9ACdo/4szDuVyCqvkrA==", - "dependencies": { - "protobufjs": "^6.11.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@hashgraph/sdk": { - "version": "2.0.29", - "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.0.29.tgz", - "integrity": "sha512-QZuzdI1jKZL2BkL7fkVA4dIqGKDVLM7BlSGoizHY0tuwSvY533bCTQRWxdlq8itR1VgzZ1iKwcSS9COwPGkqvw==", - "dependencies": { - "@grpc/grpc-js": "^1.3.4", - "@hashgraph/cryptography": "^1.0.20", - "@hashgraph/proto": "1.1.9", - "@types/crypto-js": "^4.0.2", - "@types/utf8": "^3.0.0", - "bignumber.js": "^9.0.1", - "crypto-js": "^4.0.0", - "js-base64": "^3.6.1", - "long": "^4.0.0", - "protobufjs": "^6.11.2", - "utf8": "^3.0.0" - }, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@types/crypto-js": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.0.2.tgz", - "integrity": "sha512-sCVniU+h3GcGqxOmng11BRvf9TfN9yIs8KKjB8C8d75W69cpTfZG80gau9yTx5SxF3gvHGbJhdESzzvnjtf3Og==" - }, - "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "node_modules/@types/node": { - "version": "16.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.7.tgz", - "integrity": "sha512-bxWC4rgIF/FjM7JsPvpk6ZKGITgw27qsYCbi6h4kWZWYpchOLENgvFaRBZUc64Q/M1y+X2EteahRbyo8QFCKdw==" - }, - "node_modules/@types/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-QrhvCktdm5wD48axAnjqSzPH9lOj0MiCYfMX6MSqGs2Jv+txwvdxviXiCEj8zSCWIEDU9SIJ7g9pU5KtxRgYSg==" - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "dependencies": { - "string-width": "^3.0.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "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==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-crypto": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-9.2.0.tgz", - "integrity": "sha512-jc9E7jHlOT8fYs64DIsSOdnLtxtIK1pV78O/nBamPwKdGrvFSNqMSFndxyVSuEimBNoPPNRwN+4Pb4W1RRltJA==" - }, - "node_modules/expo-random": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/expo-random/-/expo-random-11.2.0.tgz", - "integrity": "sha512-kgBJBB02iCX/kpoTHN57V7b4hWOCj4eACIQDl7bN94lycUcZu62T00P/rVZIcE/29x0GAi+Pw5ZWj0NlqBsMQQ==", - "dependencies": { - "base64-js": "^1.3.0" - } - }, - "node_modules/fastestsmallesttextencoderdecoder": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", - "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", - "dev": true, - "dependencies": { - "ini": "1.3.7" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "dev": true, - "dependencies": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/js-base64": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.6.1.tgz", - "integrity": "sha512-Frdq2+tRRGLQUIQOgsIGSCd1VePCS2fsddTG5dTCqR0JHgltXWfsxnY0gIXPoMeRmdom6Oyq+UMOFg5suduOjQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/mocha": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", - "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.2", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.7", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.23", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.5", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nodemon": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", - "integrity": "sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", - "semver": "^5.7.1", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.3", - "update-notifier": "^4.1.0" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - } - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "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==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "name": "@hashgraph/did-sdk-js", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@hashgraph/did-sdk-js", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@hashgraph/sdk": "^2.32.0", + "base58-js": "^1.0.5", + "did-resolver": "^3.1.5", + "js-base64": "^3.7.5", + "moment": "^2.29.1", + "multiformats": "^9.6.2", + "node-fetch": "^2.6.12", + "varint": "^6.0.0" + }, + "devDependencies": { + "@types/jest": "^27.4.0", + "@types/node": "^16.7.7", + "@types/node-fetch": "^2.6.4", + "jest": "^27.5.0", + "nodemon": "^2.0.7", + "prettier": "2.5.1", + "ts-jest": "^27.1.3", + "typescript": "^4.3.2" + }, + "engines": { + "node": ">=16.13.1", + "npm": ">=8.1.2" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", + "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", + "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.5", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.5", + "@babel/types": "^7.18.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", + "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", + "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", + "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", + "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.5", + "@babel/types": "^7.18.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.2.tgz", + "integrity": "sha512-5cqCjUvDKJWHGeu1prlrFOUmjuML0NequZKJ38PsCkfwIqPnZq4Q9burPP3It7/+46wpl0KsqVN3s6Te3B9Qtw==", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.8.tgz", + "integrity": "sha512-GU12e2c8dmdXb7XUlOgYWZ2o2i+z9/VeACkxTA/zzAe2IjclC5PnVL0lpgjhrqfpDYHzM8B1TF6pqWegMYAzlA==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@hashgraph/cryptography": { + "version": "1.4.8-beta.5", + "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.4.8-beta.5.tgz", + "integrity": "sha512-soq2vGLRkdl2Evr+gIvIjCXJjqA1hOAjysBGG+dhP6tKx2PEgEjb3hON/sMbxm3Q4qQdkML/vEthdAV707+flw==", + "dependencies": { + "asn1js": "^3.0.5", + "bignumber.js": "^9.1.1", + "bn.js": "^5.2.1", + "buffer": "^6.0.3", + "crypto-js": "^4.2.0", + "elliptic": "^6.5.4", + "js-base64": "^3.7.4", + "node-forge": "^1.3.1", + "spark-md5": "^3.0.2", + "tweetnacl": "^1.0.3", + "utf8": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "expo": "^49.0.16", + "expo-crypto": "^10.1.2", + "expo-random": "^12.1.2" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-crypto": { + "optional": true + }, + "expo-random": { + "optional": true + } + } + }, + "node_modules/@hashgraph/proto": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-2.15.0.tgz", + "integrity": "sha512-ULSNIwQZIroTssrEfNoUcIcWEJ9BIwKZiAsaRvJ2+Rr3XIr+np7UXv6sEkJU+jSyzk97LrTdiRAoc/hJO9Vx8Q==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@hashgraph/sdk": { + "version": "2.46.0", + "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.46.0.tgz", + "integrity": "sha512-Zyk82OLhteWAahvXzyKFdcanPI/RMjB9DMc2v1R3vog6Yaf84v1HxldtYAczQ4SPXrPdUKXk5j5Ct/19J9bRqw==", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@grpc/grpc-js": "1.8.2", + "@hashgraph/cryptography": "1.4.8-beta.5", + "@hashgraph/proto": "2.15.0", + "axios": "^1.6.4", + "bignumber.js": "^9.1.1", + "bn.js": "^5.1.1", + "crypto-js": "^4.2.0", + "js-base64": "^3.7.4", + "long": "^4.0.0", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", + "protobufjs": "^7.2.5", + "rfc4648": "^1.5.3", + "utf8": "^3.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "expo": "^49.0.16" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "dev": true, + "dependencies": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "node_modules/@types/node": { + "version": "16.11.41", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.41.tgz", + "integrity": "sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ==" + }, + "node_modules/@types/node-fetch": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", + "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base58-js": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/base58-js/-/base58-js-1.0.5.tgz", + "integrity": "sha512-LkkAPP8Zu+c0SVNRTRVDyMfKVORThX+rCViget00xdgLRrKkClCTz1T7cIrpr69ShwV5XJuuoZvMvJ43yURwkA==", + "engines": { + "node": ">= 8" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "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==" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "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==" + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", + "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001358", + "electron-to-chromium": "^1.4.164", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001359", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz", + "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/configstore/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/did-resolver": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-3.2.2.tgz", + "integrity": "sha512-Eeo2F524VM5N3W4GwglZrnul2y6TLTwMQP3In62JdG34NZoqihYyOZLk+5wUW8sSgvIYIcJM8Dlt3xsdKZZ3tg==" + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.168", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.168.tgz", + "integrity": "sha512-yz247hclRBaP8ABB1hf9kL7AMfa+yC2hB9F3XF8Y87VWMnYgq4QYvV6acRACcDkTDxfGQ4GYK/aZPQiuFMGbaA==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "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==" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/fast-copy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", + "integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/help-me": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", + "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", + "dependencies": { + "glob": "^8.0.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/help-me/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/help-me/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/help-me/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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-changed-files/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-runtime/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runtime/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runtime/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-runtime/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runtime/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "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==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multiformats": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.7.0.tgz", + "integrity": "sha512-uv/tcgwk0yN4DStopnBN4GTgvaAlYdy6KnZpuzEPFOYQd71DYFJjs0MN1ERElAflrZaYyGBWXyGxL5GgrxIx0Q==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.18.tgz", + "integrity": "sha512-uAvrKipi2zAz8E7nkSz4qW4F4zd5fs2wNGsTx+xXlP8KXqd9ucE0vY9wankOsPboeDyuUGN9vsXGV1pLn80l/A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", + "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pino": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.14.1.tgz", + "integrity": "sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.0.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^2.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.1.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", + "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.1.tgz", + "integrity": "sha512-yrn00+jNpkvZX/NrPVCPIVHAfTDy3ahF0PND9tKqZk4j9s+loK8dpzrJj4dGb7i+WLuR50ussuTAiWoMWU+qeA==", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^4.0.1", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", + "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/protobufjs": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", + "integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs/node_modules/long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/rfc4648": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", + "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sonic-boom": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", + "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spark-md5": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz", + "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==" + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/thread-stream": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", + "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-jest": { + "version": "27.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", + "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@types/jest": "^27.0.0", + "babel-jest": ">=27.0.0 <28", + "jest": "^27.0.0", + "typescript": ">=3.8 <5.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", + "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } } - ] - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", - "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "dev": true, - "dependencies": { - "debug": "^2.2.0" - } - }, - "node_modules/undefsafe/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/undefsafe/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", - "dev": true, - "dependencies": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@grpc/grpc-js": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.7.tgz", - "integrity": "sha512-CKQVuwuSPh40tgOkR7c0ZisxYRiN05PcKPW72mQL5y++qd7CwBRoaJZvU5xfXnCJDFBmS3qZGQ71Frx6Ofo2XA==", - "requires": { - "@types/node": ">=12.12.47" - } - }, - "@hashgraph/cryptography": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.0.20.tgz", - "integrity": "sha512-rdKKnENJfs0gsqAtY+7nzpG9TQshtnf+F3/PdH8z+qdy4mo4RSULBMc55FkWWNZLnoA4/34wEW8kohjFEzsLRA==", - "requires": { - "@types/crypto-js": "^4.0.2", - "@types/utf8": "^3.0.0", - "bignumber.js": "^9.0.1", - "crypto-js": "^4.0.0", - "expo-crypto": "^9.2.0", - "expo-random": "^11.2.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "js-base64": "^3.6.1", - "tweetnacl": "^1.0.3" - } - }, - "@hashgraph/proto": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-1.1.9.tgz", - "integrity": "sha512-BOY5LD8NCjFot0EFXla2ZX8Q7UE94ZDQoSKXK/XVwlLgcMNSArdIPfK4zy4EBvLZnWV9ACdo/4szDuVyCqvkrA==", - "requires": { - "protobufjs": "^6.11.2" - } - }, - "@hashgraph/sdk": { - "version": "2.0.29", - "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.0.29.tgz", - "integrity": "sha512-QZuzdI1jKZL2BkL7fkVA4dIqGKDVLM7BlSGoizHY0tuwSvY533bCTQRWxdlq8itR1VgzZ1iKwcSS9COwPGkqvw==", - "requires": { - "@grpc/grpc-js": "^1.3.4", - "@hashgraph/cryptography": "^1.0.20", - "@hashgraph/proto": "1.1.9", - "@types/crypto-js": "^4.0.2", - "@types/utf8": "^3.0.0", - "bignumber.js": "^9.0.1", - "crypto-js": "^4.0.0", - "js-base64": "^3.6.1", - "long": "^4.0.0", - "protobufjs": "^6.11.2", - "utf8": "^3.0.0" - } - }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "@types/crypto-js": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.0.2.tgz", - "integrity": "sha512-sCVniU+h3GcGqxOmng11BRvf9TfN9yIs8KKjB8C8d75W69cpTfZG80gau9yTx5SxF3gvHGbJhdESzzvnjtf3Og==" - }, - "@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "@types/node": { - "version": "16.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.7.tgz", - "integrity": "sha512-bxWC4rgIF/FjM7JsPvpk6ZKGITgw27qsYCbi6h4kWZWYpchOLENgvFaRBZUc64Q/M1y+X2EteahRbyo8QFCKdw==" - }, - "@types/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-QrhvCktdm5wD48axAnjqSzPH9lOj0MiCYfMX6MSqGs2Jv+txwvdxviXiCEj8zSCWIEDU9SIJ7g9pU5KtxRgYSg==" - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "requires": { - "string-width": "^3.0.0" - }, - "dependencies": { + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", + "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", + "dev": true + }, + "@babel/core": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", + "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.5", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.5", + "@babel/types": "^7.18.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", + "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", + "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + } + }, + "@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", + "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + } + } + }, + "@babel/traverse": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", + "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.5", + "@babel/types": "^7.18.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + } + } + }, + "@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "requires": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "requires": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "requires": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "requires": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "requires": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "requires": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==" + }, + "@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "requires": { + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "requires": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "requires": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "requires": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "@grpc/grpc-js": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.2.tgz", + "integrity": "sha512-5cqCjUvDKJWHGeu1prlrFOUmjuML0NequZKJ38PsCkfwIqPnZq4Q9burPP3It7/+46wpl0KsqVN3s6Te3B9Qtw==", + "requires": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + } + }, + "@grpc/proto-loader": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.8.tgz", + "integrity": "sha512-GU12e2c8dmdXb7XUlOgYWZ2o2i+z9/VeACkxTA/zzAe2IjclC5PnVL0lpgjhrqfpDYHzM8B1TF6pqWegMYAzlA==", + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + } + } + }, + "@hashgraph/cryptography": { + "version": "1.4.8-beta.5", + "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.4.8-beta.5.tgz", + "integrity": "sha512-soq2vGLRkdl2Evr+gIvIjCXJjqA1hOAjysBGG+dhP6tKx2PEgEjb3hON/sMbxm3Q4qQdkML/vEthdAV707+flw==", + "requires": { + "asn1js": "^3.0.5", + "bignumber.js": "^9.1.1", + "bn.js": "^5.2.1", + "buffer": "^6.0.3", + "crypto-js": "^4.2.0", + "elliptic": "^6.5.4", + "js-base64": "^3.7.4", + "node-forge": "^1.3.1", + "spark-md5": "^3.0.2", + "tweetnacl": "^1.0.3", + "utf8": "^3.0.0" + } + }, + "@hashgraph/proto": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-2.15.0.tgz", + "integrity": "sha512-ULSNIwQZIroTssrEfNoUcIcWEJ9BIwKZiAsaRvJ2+Rr3XIr+np7UXv6sEkJU+jSyzk97LrTdiRAoc/hJO9Vx8Q==", + "requires": { + "long": "^4.0.0", + "protobufjs": "^7.2.5" + } + }, + "@hashgraph/sdk": { + "version": "2.46.0", + "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.46.0.tgz", + "integrity": "sha512-Zyk82OLhteWAahvXzyKFdcanPI/RMjB9DMc2v1R3vog6Yaf84v1HxldtYAczQ4SPXrPdUKXk5j5Ct/19J9bRqw==", + "requires": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@grpc/grpc-js": "1.8.2", + "@hashgraph/cryptography": "1.4.8-beta.5", + "@hashgraph/proto": "2.15.0", + "axios": "^1.6.4", + "bignumber.js": "^9.1.1", + "bn.js": "^5.1.1", + "crypto-js": "^4.2.0", + "js-base64": "^3.7.4", + "long": "^4.0.0", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", + "protobufjs": "^7.2.5", + "rfc4648": "^1.5.3", + "utf8": "^3.0.0" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "dev": true, + "requires": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "@types/node": { + "version": "16.11.41", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.41.tgz", + "integrity": "sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ==" + }, + "@types/node-fetch": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", + "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" + }, + "axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base58-js": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/base58-js/-/base58-js-1.0.5.tgz", + "integrity": "sha512-LkkAPP8Zu+c0SVNRTRVDyMfKVORThX+rCViget00xdgLRrKkClCTz1T7cIrpr69ShwV5XJuuoZvMvJ43yURwkA==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "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==" + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browserslist": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", + "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001358", + "electron-to-chromium": "^1.4.164", + "node-releases": "^2.0.5", + "update-browserslist-db": "^1.0.0" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001359", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz", + "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "did-resolver": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-3.2.2.tgz", + "integrity": "sha512-Eeo2F524VM5N3W4GwglZrnul2y6TLTwMQP3In62JdG34NZoqihYyOZLk+5wUW8sSgvIYIcJM8Dlt3xsdKZZ3tg==" + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.168", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.168.tgz", + "integrity": "sha512-yz247hclRBaP8ABB1hf9kL7AMfa+yC2hB9F3XF8Y87VWMnYgq4QYvV6acRACcDkTDxfGQ4GYK/aZPQiuFMGbaA==", + "dev": true + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "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" + }, + "dependencies": { + "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==" + } + } + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true + }, + "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==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "fast-copy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-redact": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", + "integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==" + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "requires": { + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "help-me": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", + "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", + "requires": { + "glob": "^8.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + } + } + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "requires": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + } + }, + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + } + }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + } + }, + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "requires": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + } + }, + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "requires": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + } + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "requires": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==" + }, + "js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "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==" + }, + "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==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multiformats": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.7.0.tgz", + "integrity": "sha512-uv/tcgwk0yN4DStopnBN4GTgvaAlYdy6KnZpuzEPFOYQd71DYFJjs0MN1ERElAflrZaYyGBWXyGxL5GgrxIx0Q==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "nodemon": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.18.tgz", + "integrity": "sha512-uAvrKipi2zAz8E7nkSz4qW4F4zd5fs2wNGsTx+xXlP8KXqd9ucE0vY9wankOsPboeDyuUGN9vsXGV1pLn80l/A==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "on-exit-leak-free": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", + "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pino": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.14.1.tgz", + "integrity": "sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==", + "requires": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.0.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^2.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.1.0", + "thread-stream": "^2.0.0" + } + }, + "pino-abstract-transport": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", + "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", + "requires": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "pino-pretty": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.1.tgz", + "integrity": "sha512-yrn00+jNpkvZX/NrPVCPIVHAfTDy3ahF0PND9tKqZk4j9s+loK8dpzrJj4dGb7i+WLuR50ussuTAiWoMWU+qeA==", + "requires": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^4.0.1", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true + }, + "prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "process-warning": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", + "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "protobufjs": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", + "integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "dependencies": { + "long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "requires": { + "tslib": "^2.6.1" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==" + }, + "quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==" + }, + "registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "requires": { + "rc": "1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "rfc4648": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", + "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + } + }, + "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==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "sonic-boom": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", + "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", + "requires": { + "atomic-sleep": "^1.0.0" + } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spark-md5": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz", + "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==" + }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "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==" + } + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "requires": { - "base-x": "^3.0.2" - } - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, - "crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" - }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "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==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "expo-crypto": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-9.2.0.tgz", - "integrity": "sha512-jc9E7jHlOT8fYs64DIsSOdnLtxtIK1pV78O/nBamPwKdGrvFSNqMSFndxyVSuEimBNoPPNRwN+4Pb4W1RRltJA==" - }, - "expo-random": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/expo-random/-/expo-random-11.2.0.tgz", - "integrity": "sha512-kgBJBB02iCX/kpoTHN57V7b4hWOCj4eACIQDl7bN94lycUcZu62T00P/rVZIcE/29x0GAi+Pw5ZWj0NlqBsMQQ==", - "requires": { - "base64-js": "^1.3.0" - } - }, - "fastestsmallesttextencoderdecoder": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", - "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", - "dev": true, - "requires": { - "ini": "1.3.7" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "dev": true, - "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - } - }, - "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-base64": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.6.1.tgz", - "integrity": "sha512-Frdq2+tRRGLQUIQOgsIGSCd1VePCS2fsddTG5dTCqR0JHgltXWfsxnY0gIXPoMeRmdom6Oyq+UMOFg5suduOjQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mocha": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", - "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.2", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.7", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.23", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.5", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - } - }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", - "dev": true - }, - "nodemon": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", - "integrity": "sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==", - "dev": true, - "requires": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", - "semver": "^5.7.1", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.3", - "update-notifier": "^4.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, - "protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - } - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "requires": { - "escape-goat": "^2.0.0" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - } - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "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==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true - }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - } - }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typescript": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", - "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", - "dev": true - }, - "undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "dev": true, - "requires": { - "debug": "^2.2.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", - "dev": true, - "requires": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } - }, - "utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, - "workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "thread-stream": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", + "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", + "requires": { + "real-require": "^0.2.0" + } + }, + "throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "ts-jest": { + "version": "27.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", + "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "dependencies": { + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, + "varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "ws": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", + "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", + "dev": true, + "requires": {} + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true } - } } diff --git a/package.json b/package.json index 0aad9dd..a232304 100644 --- a/package.json +++ b/package.json @@ -1,43 +1,56 @@ { - "name": "@hashgraph/did-sdk-js", - "version": "0.1.1", - "description": "Support for the Hedera Hashgraph DID Method and Verifiable Credentials on the Hedera JavaScript/TypeScript SDK", - "main": "dist/index.js", - "module": "dist/index.js", - "files": [ - "dist/**/*" - ], - "types": "dist/index.d.ts", - "scripts": { - "prepare": "npm run build", - "prepublish": "npm run build", - "build": "tsc", - "build:dev": "tsc --sourceMap -w", - "start": "node dist/index.js", - "start:dev": "nodemon --inspect dist/index.js", - "test": "mocha test/**/*.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/hashgraph/did-sdk-js.git" - }, - "author": "Hedera Hashgraph, LLC", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/hashgraph/did-sdk-js/issues" - }, - "homepage": "https://github.com/hashgraph/did-sdk-js#readme", - "devDependencies": { - "@types/node": "^16.7.7", - "chai": "^4.3.4", - "mocha": "^9.0.1", - "nodemon": "^2.0.7", - "typescript": "^4.3.2" - }, - "dependencies": { - "@hashgraph/sdk": "^2.0.20", - "bs58": "^4.0.1", - "js-base64": "^3.6.1", - "moment": "^2.29.1" - } + "name": "@hashgraph/did-sdk-js", + "version": "1.0.0", + "engines": { + "npm": ">=8.1.2", + "node": ">=16.13.1" + }, + "description": "Support for the Hedera Hashgraph DID Method on the Hedera JavaScript/TypeScript SDK", + "main": "dist/index.js", + "module": "dist/index.js", + "files": [ + "dist/**/*" + ], + "types": "dist/index.d.ts", + "scripts": { + "prepare": "npm run build", + "prepublish": "npm run build", + "build": "tsc", + "build:dev": "tsc --sourceMap -w", + "start": "node dist/index.js", + "start:dev": "nodemon --inspect dist/index.js", + "test": "jest --runInBand --detectOpenHandles --forceExit", + "test:unit": "jest --testPathPattern=test/unit", + "test:integration": "jest --testPathPattern=test/integration --runInBand --detectOpenHandles --forceExit" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hashgraph/did-sdk-js.git" + }, + "author": "Hedera Hashgraph, LLC", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/hashgraph/did-sdk-js/issues" + }, + "homepage": "https://github.com/hashgraph/did-sdk-js#readme", + "devDependencies": { + "@types/jest": "^27.4.0", + "@types/node": "^16.7.7", + "@types/node-fetch": "^2.6.4", + "jest": "^27.5.0", + "nodemon": "^2.0.7", + "prettier": "2.5.1", + "ts-jest": "^27.1.3", + "typescript": "^4.3.2" + }, + "dependencies": { + "@hashgraph/sdk": "^2.32.0", + "base58-js": "^1.0.5", + "did-resolver": "^3.1.5", + "js-base64": "^3.7.5", + "moment": "^2.29.1", + "multiformats": "^9.6.2", + "node-fetch": "^2.6.12", + "varint": "^6.0.0" + } } diff --git a/src/identity/did-document-base.ts b/src/identity/did-document-base.ts deleted file mode 100644 index dee2bd4..0000000 --- a/src/identity/did-document-base.ts +++ /dev/null @@ -1,73 +0,0 @@ -import {DidSyntax} from "./did-syntax"; -import {DidDocumentJsonProperties} from "./did-document-json-properties"; -import {HcsDidRootKey} from "./hcs/did/hcs-did-root-key"; - -export class DidDocumentBase { - private id: string; - private context: string; - private didRootKey: HcsDidRootKey; - - constructor(did: string) { - this.id = did; - this.context = DidSyntax.DID_DOCUMENT_CONTEXT; - } - - public static fromJson(json: string): DidDocumentBase { - let result: DidDocumentBase; - - try { - const root = JSON.parse(json); - result = new DidDocumentBase(root.id); - if (root.hasOwnProperty(DidDocumentJsonProperties.PUBLIC_KEY)) { - if (!Array.isArray(root[DidDocumentJsonProperties.PUBLIC_KEY])) { - throw new Error(`${root[DidDocumentJsonProperties.PUBLIC_KEY]} is not an array`); - } - for (let publicKeyObj of root[DidDocumentJsonProperties.PUBLIC_KEY]) { - if (publicKeyObj.hasOwnProperty(DidDocumentJsonProperties.ID) && (publicKeyObj[DidDocumentJsonProperties.ID] === - (result.getId() + HcsDidRootKey.DID_ROOT_KEY_NAME))) { - const didRootKey = HcsDidRootKey.fromJsonTree(publicKeyObj); - result.setDidRootKey(didRootKey); - break; - } - } - } - } catch (e) { - throw new Error('Given JSON string is not a valid DID document ' + e.message); - } - - return result; - } - - public getContext(): string { - return this.context; - } - - public getId(): string { - return this.id; - } - - public getDidRootKey(): HcsDidRootKey { - return this.didRootKey; - } - - public setDidRootKey(rootKey: HcsDidRootKey): void { - this.didRootKey = rootKey - } - - public toJsonTree(): any { - const rootObject = {}; - rootObject[DidDocumentJsonProperties.CONTEXT] = this.context; - rootObject[DidDocumentJsonProperties.ID] = this.id; - rootObject[DidDocumentJsonProperties.PUBLIC_KEY] = [ - this.didRootKey.toJsonTree() - ]; - rootObject[DidDocumentJsonProperties.AUTHENTICATION] = [ - this.didRootKey.getId() - ]; - return rootObject; - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } -} diff --git a/src/identity/did-document-json-properties.ts b/src/identity/did-document-json-properties.ts index d34637d..55837a8 100644 --- a/src/identity/did-document-json-properties.ts +++ b/src/identity/did-document-json-properties.ts @@ -1,10 +1,12 @@ export module DidDocumentJsonProperties { - export const CONTEXT = '@context'; - export const ID = 'id'; - export const AUTHENTICATION = 'authentication'; - export const PUBLIC_KEY = 'publicKey'; - export const SERVICE = 'service'; - export const CREATED = 'created'; - export const UPDATED = 'updated'; - export const PROOF = 'proof'; + export const CONTEXT = "@context"; + export const ID = "id"; + export const CONTROLLER = "controller"; + export const AUTHENTICATION = "authentication"; + export const VERIFICATION_METHOD = "verificationMethod"; + export const ASSERTION_METHOD = "assertionMethod"; + export const KEY_AGREEMENT = "keyAgreement"; + export const CAPABILITY_INVOCATION = "capabilityInvocation"; + export const CAPABILITY_DELEGATION = "capabilityDelegation"; + export const SERVICE = "service"; } diff --git a/src/identity/did-document.ts b/src/identity/did-document.ts new file mode 100644 index 0000000..461970f --- /dev/null +++ b/src/identity/did-document.ts @@ -0,0 +1,425 @@ +import { Timestamp } from "@hashgraph/sdk"; +import { + DidMethodOperation, + HcsDidCreateDidOwnerEvent, + HcsDidCreateServiceEvent, + HcsDidMessage, + HcsDidUpdateDidOwnerEvent, +} from ".."; +import { IpfsDidDocumentDownloader } from "../utils/ipfs"; +import { DidDocumentJsonProperties } from "./did-document-json-properties"; +import { DidSyntax } from "./did-syntax"; +import { HcsDidCreateDidDocumentEvent } from "./hcs/did/event/document/hcs-did-create-did-document-event"; +import { HcsDidEventTargetName } from "./hcs/did/event/hcs-did-event-target-name"; +import { HcsDidUpdateServiceEvent } from "./hcs/did/event/service/hcs-did-update-service-event"; +import { HcsDidCreateVerificationMethodEvent } from "./hcs/did/event/verification-method/hcs-did-create-verification-method-event"; +import { HcsDidUpdateVerificationMethodEvent } from "./hcs/did/event/verification-method/hcs-did-update-verification-method-event"; +import { HcsDidCreateVerificationRelationshipEvent } from "./hcs/did/event/verification-relationship/hcs-did-create-verification-relationship-event"; +import { HcsDidRevokeVerificationRelationshipEvent } from "./hcs/did/event/verification-relationship/hcs-did-revoke-verification-relationship-event"; +import { HcsDidUpdateVerificationRelationshipEvent } from "./hcs/did/event/verification-relationship/hcs-did-update-verification-relationship-event"; + +export class DidDocument { + private readonly id: string; + private readonly context: string; + + private created: Timestamp = null; + private updated: Timestamp = null; + private versionId: string = null; + private deactivated: boolean = false; + private downloader: IpfsDidDocumentDownloader = new IpfsDidDocumentDownloader(); + + private controller: any; + private services: Map = new Map(); + private verificationMethods: Map = new Map(); + + private verificationRelationships: { [key: string]: string[] } = { + authentication: [], + assertionMethod: [], + keyAgreement: [], + capabilityInvocation: [], + capabilityDelegation: [], + }; + + constructor(did: string) { + this.id = did; + this.context = DidSyntax.DID_DOCUMENT_CONTEXT; + } + + public hasOwner() { + return !!this.controller; + } + + public getContext(): string { + return this.context; + } + + public getId(): string { + return this.id; + } + + public getCreated() { + return this.created; + } + + public getUpdated() { + return this.updated; + } + + public getVersionId() { + return this.versionId; + } + + public getDeactivated() { + return this.deactivated; + } + + public async processMessages(messages: HcsDidMessage[]): Promise { + for (const msg of messages) { + if ( + !this.controller && + msg.getOperation() === DidMethodOperation.CREATE && + msg.getEvent().targetName !== HcsDidEventTargetName.DID_OWNER && + msg.getEvent().targetName !== HcsDidEventTargetName.DID_DOCUMENT + ) { + console.warn("DID document owner is not registered. Event will be ignored..."); + continue; + } + + switch (msg.getOperation()) { + case DidMethodOperation.CREATE: + await this.processCreateMessage(msg); + continue; + case DidMethodOperation.UPDATE: + await this.processUpdateMessage(msg); + continue; + case DidMethodOperation.REVOKE: + await this.processRevokeMessage(msg); + continue; + case DidMethodOperation.DELETE: + await this.processDeleteMessage(msg); + continue; + default: + console.warn(`Operation ${msg.getOperation()} is not supported. Event will be ignored...`); + } + } + } + + public setIpfsDownloader(downloader: IpfsDidDocumentDownloader) { + this.downloader = downloader; + } + + public toJsonTree(): any { + let rootObject = {}; + + rootObject[DidDocumentJsonProperties.CONTEXT] = this.context; + rootObject[DidDocumentJsonProperties.ID] = this.id; + + if (this.controller && this.id !== this.controller && this.id !== this.controller.controller) { + rootObject[DidDocumentJsonProperties.CONTROLLER] = this.controller.controller ?? this.controller; + } + + rootObject[DidDocumentJsonProperties.VERIFICATION_METHOD] = Array.from(this.verificationMethods.values()); + + rootObject[DidDocumentJsonProperties.ASSERTION_METHOD] = [ + ...this.verificationRelationships[DidDocumentJsonProperties.ASSERTION_METHOD], + ]; + + rootObject[DidDocumentJsonProperties.AUTHENTICATION] = [ + ...this.verificationRelationships[DidDocumentJsonProperties.AUTHENTICATION], + ]; + + if (this.controller) { + rootObject[DidDocumentJsonProperties.VERIFICATION_METHOD].unshift(this.controller); + rootObject[DidDocumentJsonProperties.ASSERTION_METHOD].unshift(this.controller.id); + rootObject[DidDocumentJsonProperties.AUTHENTICATION].unshift(this.controller.id); + } + + if (this.verificationRelationships[DidDocumentJsonProperties.KEY_AGREEMENT].length > 0) { + rootObject[DidDocumentJsonProperties.KEY_AGREEMENT] = [ + ...this.verificationRelationships[DidDocumentJsonProperties.KEY_AGREEMENT], + ]; + } + if (this.verificationRelationships[DidDocumentJsonProperties.CAPABILITY_INVOCATION].length > 0) { + rootObject[DidDocumentJsonProperties.CAPABILITY_INVOCATION] = [ + ...this.verificationRelationships[DidDocumentJsonProperties.CAPABILITY_INVOCATION], + ]; + } + if (this.verificationRelationships[DidDocumentJsonProperties.CAPABILITY_DELEGATION].length > 0) { + rootObject[DidDocumentJsonProperties.CAPABILITY_DELEGATION] = [ + ...this.verificationRelationships[DidDocumentJsonProperties.CAPABILITY_DELEGATION], + ]; + } + + if (this.services.size > 0) { + rootObject[DidDocumentJsonProperties.SERVICE] = [...Array.from(this.services.values())]; + } + + return rootObject; + } + + public toJSON(): string { + return JSON.stringify(this.toJsonTree()); + } + + private setDocumentActivated(message: HcsDidMessage): void { + const timestamp = message.getTimestamp(); + + this.created = timestamp; + this.updated = timestamp; + this.deactivated = false; + this.versionId = timestamp.toDate().getTime().toString(); + } + + private setDocumentDeactivated(): void { + this.created = null; + this.updated = null; + this.deactivated = true; + this.versionId = null; + } + + private setDocumentUpdated(message: HcsDidMessage): void { + const timestamp = message.getTimestamp(); + + this.updated = timestamp; + this.versionId = timestamp.toDate().getTime().toString(); + } + + private async processCreateMessage(message: HcsDidMessage): Promise { + const event = message.getEvent(); + + switch (event.targetName) { + case HcsDidEventTargetName.DID_DOCUMENT: + const doc = await this.downloader.downloadDocument(event as HcsDidCreateDidDocumentEvent); + if (doc[DidDocumentJsonProperties.ID] !== this.id) { + throw new Error("Document ID does not match did"); + } + this.controller = doc[DidDocumentJsonProperties.CONTROLLER]; + + this.services = new Map( + (doc[DidDocumentJsonProperties.SERVICE] ?? []).map((service) => [service.id, service]) + ); + this.verificationMethods = new Map( + (doc[DidDocumentJsonProperties.VERIFICATION_METHOD] ?? []).map((verificationMethod) => [ + verificationMethod.id, + verificationMethod, + ]) + ); + + this.verificationRelationships[DidDocumentJsonProperties.ASSERTION_METHOD] = + doc[DidDocumentJsonProperties.ASSERTION_METHOD] ?? []; + this.verificationRelationships[DidDocumentJsonProperties.AUTHENTICATION] = + doc[DidDocumentJsonProperties.AUTHENTICATION] ?? []; + this.verificationRelationships[DidDocumentJsonProperties.KEY_AGREEMENT] = + doc[DidDocumentJsonProperties.KEY_AGREEMENT] ?? []; + this.verificationRelationships[DidDocumentJsonProperties.CAPABILITY_INVOCATION] = + doc[DidDocumentJsonProperties.CAPABILITY_INVOCATION] ?? []; + this.verificationRelationships[DidDocumentJsonProperties.CAPABILITY_DELEGATION] = + doc[DidDocumentJsonProperties.CAPABILITY_DELEGATION] ?? []; + + return; + + case HcsDidEventTargetName.DID_OWNER: + if (this.controller) { + console.warn(`DID owner is already registered: ${this.controller}. Event will be ignored...`); + return; + } + + this.controller = (event as HcsDidCreateDidOwnerEvent).getOwnerDef(); + this.setDocumentActivated(message); + return; + case HcsDidEventTargetName.SERVICE: + if (this.services.has(event.getId())) { + console.warn(`Duplicate create Service event ID: ${event.getId()}. Event will be ignored...`); + return; + } + this.services.set(event.getId(), (event as HcsDidCreateServiceEvent).getServiceDef()); + this.setDocumentUpdated(message); + return; + case HcsDidEventTargetName.VERIFICATION_METHOD: + if (this.verificationMethods.has(event.getId())) { + console.warn( + `Duplicate create VerificationMethod event ID: ${event.getId()}. Event will be ignored...` + ); + return; + } + + this.verificationMethods.set( + event.getId(), + (event as HcsDidCreateVerificationMethodEvent).getVerificationMethodDef() + ); + this.setDocumentUpdated(message); + return; + case HcsDidEventTargetName.VERIFICATION_RELATIONSHIP: + const type = (event as HcsDidCreateVerificationRelationshipEvent).getRelationshipType(); + + if (this.verificationRelationships[type]) { + if (this.verificationRelationships[type].includes(event.getId())) { + console.warn( + `Duplicate create VerificationRelationship event ID: ${event.getId()}. Event will be ignored...` + ); + return; + } + + this.verificationRelationships[type].push(event.getId()); + + if (!this.verificationMethods.has(event.getId())) { + this.verificationMethods.set( + event.getId(), + (event as HcsDidCreateVerificationRelationshipEvent).getVerificationMethodDef() + ); + } + this.setDocumentUpdated(message); + } else { + console.warn( + `Create verificationRelationship event with type ${type} is not supported. Event will be ignored...` + ); + } + return; + default: + console.warn(`Create ${event.targetName} operation is not supported. Event will be ignored...`); + } + } + + private async processUpdateMessage(message: HcsDidMessage): Promise { + const event = message.getEvent(); + + switch (event.targetName) { + case HcsDidEventTargetName.DID_OWNER: + this.controller = (event as HcsDidUpdateDidOwnerEvent).getOwnerDef(); + this.setDocumentUpdated(message); + return; + case HcsDidEventTargetName.SERVICE: + if (!this.services.has(event.getId())) { + console.warn( + `Update Service event: service with ID ${event.getId()} was not found in the document. Event will be ignored...` + ); + return; + } + this.services.set(event.getId(), (event as HcsDidUpdateServiceEvent).getServiceDef()); + this.setDocumentUpdated(message); + return; + case HcsDidEventTargetName.VERIFICATION_METHOD: + if (!this.verificationMethods.has(event.getId())) { + console.warn( + `Update VerificationMethod event: verificationMethod with ID: ${event.getId()} was not found in the document. Event will be ignored...` + ); + return; + } + + this.verificationMethods.set( + event.getId(), + (event as HcsDidUpdateVerificationMethodEvent).getVerificationMethodDef() + ); + this.setDocumentUpdated(message); + return; + case HcsDidEventTargetName.VERIFICATION_RELATIONSHIP: + const type = (event as HcsDidUpdateVerificationRelationshipEvent).getRelationshipType(); + + if (this.verificationRelationships[type]) { + if (!this.verificationRelationships[type].includes(event.getId())) { + console.warn( + `Update VerificationRelationship event: verificationRelationship with ID: ${event.getId()} was not found in the document. Event will be ignored...` + ); + return; + } + + this.verificationMethods.set( + event.getId(), + (event as HcsDidUpdateVerificationRelationshipEvent).getVerificationMethodDef() + ); + this.setDocumentUpdated(message); + } else { + console.warn( + `Update verificationRelationship event with type ${type} is not supported. Event will be ignored...` + ); + } + return; + default: + console.warn(`Update ${event.targetName} operation is not supported. Event will be ignored...`); + } + } + + private async processRevokeMessage(message: HcsDidMessage): Promise { + const event = message.getEvent(); + + switch (event.targetName) { + case HcsDidEventTargetName.SERVICE: + if (!this.services.has(event.getId())) { + console.warn(`Revoke Service event: service event ID: ${event.getId()}. Event will be ignored...`); + return; + } + + this.services.delete(event.getId()); + this.setDocumentUpdated(message); + return; + case HcsDidEventTargetName.VERIFICATION_METHOD: + if (!this.verificationMethods.has(event.getId())) { + console.warn( + `Revoke VerificationMethod event: verificationMethod with ID: ${event.getId()}. Event will be ignored...` + ); + return; + } + + this.verificationMethods.delete(event.getId()); + + Object.keys(this.verificationRelationships).forEach((relName) => { + this.verificationRelationships[relName] = this.verificationRelationships[relName].filter( + (id) => id !== event.getId() + ); + }); + this.setDocumentUpdated(message); + + return; + case HcsDidEventTargetName.VERIFICATION_RELATIONSHIP: + const type = (event as HcsDidRevokeVerificationRelationshipEvent).getRelationshipType(); + + if (this.verificationRelationships[type]) { + if (!this.verificationRelationships[type].includes(event.getId())) { + console.warn( + `Revoke VerificationRelationship event: verificationRelationship with ID: ${event.getId()}. Event will be ignored...` + ); + return; + } + + this.verificationRelationships[type] = this.verificationRelationships[type].filter( + (id) => id !== event.getId() + ); + + const canRemoveVerificationMethod = Object.values(this.verificationRelationships).every( + (rel) => !rel.includes(event.getId()) + ); + + if (canRemoveVerificationMethod) { + this.verificationMethods.delete(event.getId()); + } + + this.setDocumentUpdated(message); + } else { + console.warn( + `Revoke verificationRelationship event with type ${type} is not supported. Event will be ignored...` + ); + } + return; + default: + console.warn(`Revoke ${event.targetName} operation is not supported. Event will be ignored...`); + } + } + + private async processDeleteMessage(message: HcsDidMessage): Promise { + const event = message.getEvent(); + + switch (event.targetName) { + case HcsDidEventTargetName.Document: + this.controller = null; + this.services.clear(); + this.verificationMethods.clear(); + Object.keys(this.verificationRelationships).forEach( + (relName) => (this.verificationRelationships[relName] = []) + ); + this.setDocumentDeactivated(); + return; + default: + console.warn(`Delete ${event.targetName} operation is not supported. Event will be ignored...`); + } + } +} diff --git a/src/identity/did-error.ts b/src/identity/did-error.ts new file mode 100644 index 0000000..368da91 --- /dev/null +++ b/src/identity/did-error.ts @@ -0,0 +1,18 @@ +export enum DidErrorCode { + GENERIC = "generic", + INVALID_DID_STRING = "invalid_did_string", + INVALID_NETWORK = "invalid_network", + /** + * DID_NOT_FOUND is not thrown anywhere at the moment + */ + DID_NOT_FOUND = "did_not_found", +} + +export class DidError extends Error { + public code: DidErrorCode; + + constructor(message: string, code: DidErrorCode = DidErrorCode.GENERIC) { + super(message); + this.code = code; + } +} diff --git a/src/identity/did-method-operation.ts b/src/identity/did-method-operation.ts index 0b794cf..d687df2 100644 --- a/src/identity/did-method-operation.ts +++ b/src/identity/did-method-operation.ts @@ -1,5 +1,7 @@ export enum DidMethodOperation { - CREATE = 'create', - UPDATE = 'update', - DELETE = 'delete' + CREATE = "create", + CREATE_DID_DOCUMENT = "create-did-document", + UPDATE = "update", + DELETE = "delete", + REVOKE = "revoke", } diff --git a/src/identity/did-parser.ts b/src/identity/did-parser.ts index 6ddccb4..ff53741 100644 --- a/src/identity/did-parser.ts +++ b/src/identity/did-parser.ts @@ -1,6 +1,6 @@ -import {HederaDid} from "./hedera-did"; -import {DidSyntax} from "./did-syntax"; -import {HcsDid} from "./hcs/did/hcs-did"; +import { DidError } from "./did-error"; +import { DidSyntax } from "./did-syntax"; +import { HcsDid } from "./hcs/did/hcs-did"; /** * Parses the given DID string into it's corresponding Hedera DID object. @@ -9,16 +9,16 @@ import {HcsDid} from "./hcs/did/hcs-did"; * @return {@link HederaDid} instance. */ export class DidParser { - public static parse(didString: string): HederaDid { + public static parse(didString: string): HcsDid { const methodIndex = DidSyntax.DID_PREFIX.length + 1; if (!didString || didString.length <= methodIndex) { - throw new Error('DID string cannot be null'); + throw new DidError("DID string cannot be null"); } if (didString.startsWith(HcsDid.DID_METHOD + DidSyntax.DID_METHOD_SEPARATOR, methodIndex)) { - return HcsDid.fromString(didString); + return new HcsDid({ identifier: didString }); } else { - throw new Error('DID string is invalid.'); + throw new DidError("DID string is invalid."); } } } diff --git a/src/identity/did-resolver.ts b/src/identity/did-resolver.ts new file mode 100644 index 0000000..20f8bc7 --- /dev/null +++ b/src/identity/did-resolver.ts @@ -0,0 +1,111 @@ +import { Client } from "@hashgraph/sdk"; +import { + DIDDocumentMetadata, + DIDResolutionOptions, + DIDResolutionResult, + DIDResolver, + ParsedDID, + Resolvable, +} from "did-resolver"; +import { DidErrorCode } from "./did-error"; +import { DidSyntax } from "./did-syntax"; +import { HcsDid } from "./hcs/did/hcs-did"; + +export enum Errors { + /** + * The resolver has failed to construct the DID document. + * This can be caused by a network issue, a wrong registry address or malformed logs while parsing the registry history. + * Please inspect the `DIDResolutionMetadata.message` to debug further. + */ + notFound = "notFound", + + /** + * The resolver does not know how to resolve the given DID. Most likely it is not a `did:hedera`. + */ + invalidDid = "invalidDid", + + /** + * The resolver is misconfigured or is being asked to resolve a DID anchored on an unknown network + */ + unknownNetwork = "unknownNetwork", +} + +export function getResolver(client?: Client): Record { + return new HederaDidResolver(client).build(); +} + +export class HederaDidResolver { + private client: Client; + + constructor(client?: Client) { + this.client = client; + } + + public getClient(networkName: string) { + if (this.client) { + return this.client; + } + + return Client.forName(networkName); + } + + async resolve( + did: string, + _parsed: ParsedDID, + _unused: Resolvable, + options: DIDResolutionOptions + ): Promise { + const networkName = did?.split(DidSyntax.DID_METHOD_SEPARATOR)[2]; + const client = this.getClient(networkName); + + try { + const registeredDid = new HcsDid({ identifier: did, client: client }); + const didDocument = await registeredDid.resolve(); + const status: Partial = didDocument.getDeactivated() ? { deactivated: true } : {}; + + let documentMeta: Partial = { + versionId: didDocument.getVersionId(), + }; + + if (!status.deactivated) { + documentMeta = { + ...documentMeta, + created: didDocument.getCreated()?.toDate()?.toISOString(), + updated: didDocument.getUpdated()?.toDate()?.toISOString(), + }; + } + + return { + didDocumentMetadata: { ...status, ...documentMeta }, + didResolutionMetadata: { contentType: "application/did+ld+json" }, + didDocument: didDocument.toJsonTree(), + }; + } catch (e: any) { + return { + didResolutionMetadata: { + error: this.getErrorCode(e), + message: e.toString(), // This is not in spec, but may be helpful + }, + didDocumentMetadata: {}, + didDocument: null, + }; + } + } + + build(): Record { + return { hedera: this.resolve.bind(this) }; + } + + private getErrorCode(error: any): Errors { + switch (error?.code) { + case DidErrorCode.INVALID_DID_STRING: + return Errors.invalidDid; + case DidErrorCode.INVALID_NETWORK: + return Errors.unknownNetwork; + case DidErrorCode.DID_NOT_FOUND: + return Errors.notFound; + default: + return Errors.notFound; + } + } +} diff --git a/src/identity/did-syntax.ts b/src/identity/did-syntax.ts index f994baf..932b125 100644 --- a/src/identity/did-syntax.ts +++ b/src/identity/did-syntax.ts @@ -1,16 +1,13 @@ export module DidSyntax { - export const DID_PREFIX = 'did'; - export const DID_DOCUMENT_CONTEXT = 'https://www.w3.org/ns/did/v1'; - export const DID_METHOD_SEPARATOR = ':'; - export const DID_PARAMETER_SEPARATOR = ';'; - export const DID_PARAMETER_VALUE_SEPARATOR = '='; + export const DID_PREFIX = "did"; + export const DID_DOCUMENT_CONTEXT = "https://www.w3.org/ns/did/v1"; + export const DID_METHOD_SEPARATOR = ":"; + export const DID_TOPIC_SEPARATOR = "_"; + export const HEDERA_NETWORK_MAINNET = "mainnet"; + export const HEDERA_NETWORK_TESTNET = "testnet"; + export const HEDERA_NETWORK_PREVIEWNET = "previewnet"; export enum Method { - HEDERA_HCS = 'hedera', - } - - export module MethodSpecificParameter { - export const ADDRESS_BOOK_FILE_ID = 'fid'; - export const DID_TOPIC_ID = 'tid'; + HEDERA_HCS = "hedera", } } diff --git a/src/identity/hcs/address-book.ts b/src/identity/hcs/address-book.ts deleted file mode 100644 index 8d0f446..0000000 --- a/src/identity/hcs/address-book.ts +++ /dev/null @@ -1,109 +0,0 @@ -import {FileId} from "@hashgraph/sdk"; - -/** - * Appnet's address book for HCS identity network. - */ -export class AddressBook { - private fileId: FileId; - private appnetName: string; - private didTopicId: string; - private vcTopicId: string; - private appnetDidServers: string[]; - - /** - * Converts an address book JSON string into address book object. - * - * @param json Address book JSON file. - * @param addressBookFileId FileId of this address book in Hedera File Service. - * @return The {@link AddressBook}. - */ - public static fromJson(json: string, addressBookFileId: FileId | string): AddressBook { - const result = new AddressBook(); - const item = JSON.parse(json); - result.appnetName = item.appnetName; - result.didTopicId = item.didTopicId; - result.vcTopicId = item.vcTopicId; - result.appnetDidServers = item.appnetDidServers; - - if (typeof addressBookFileId === 'string') { - result.setFileId(FileId.fromString(addressBookFileId)); - } else if (addressBookFileId instanceof FileId) { - result.setFileId(addressBookFileId); - } - - return result; - } - - /** - * Creates a new {@link AddressBook} instance. Does not create the file on Hedera File Service!. - * - * @param appnetName Name of the appnet. - * @param didTopicId TopicID of the DID topic. - * @param vcTopicId Topic ID of the Verifiable Credentials topic. - * @param appnetDidServers List of appnet API servers. - * @return The {@link AddressBook}. - */ - public static create(appnetName: string, didTopicId: string, vcTopicId: string, appnetDidServers: string[]) { - const result = new AddressBook(); - result.appnetDidServers = appnetDidServers; - result.didTopicId = didTopicId; - result.vcTopicId = vcTopicId; - result.appnetName = appnetName; - - return result; - } - - /** - * Converts this address book file into JSON string. - * - * @return The JSON representation of this address book. - */ - public toJSON(): string { - return JSON.stringify({ - appnetName: this.appnetName, - didTopicId: this.didTopicId, - vcTopicId: this.vcTopicId, - appnetDidServers: this.appnetDidServers - }); - } - - public getAppnetName(): string { - return this.appnetName; - } - - public setAppnetName(appnetName: string): void { - this.appnetName = appnetName; - } - - public getDidTopicId(): string { - return this.didTopicId; - } - - public setDidTopicId(didTopicId: string): void { - this.didTopicId = didTopicId; - } - - public getVcTopicId(): string { - return this.vcTopicId; - } - - public setVcTopicId(vcTopicId: string): void { - this.vcTopicId = vcTopicId; - } - - public getAppnetDidServers(): string[] { - return this.appnetDidServers; - } - - public setAppnetDidServers(appnetDidServers: string[]): void { - this.appnetDidServers = appnetDidServers; - } - - public getFileId(): FileId { - return this.fileId; - } - - public setFileId(fileId: FileId): void { - this.fileId = fileId; - } -} diff --git a/src/identity/hcs/did/event/document/hcs-did-create-did-document-event.ts b/src/identity/hcs/did/event/document/hcs-did-create-did-document-event.ts new file mode 100644 index 0000000..4d1827d --- /dev/null +++ b/src/identity/hcs/did/event/document/hcs-did-create-did-document-event.ts @@ -0,0 +1,65 @@ +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; + +export class HcsDidCreateDidDocumentEvent extends HcsDidEvent { + public static DID_DOCUMENT_TYPE = "DIDDocument"; + + public readonly targetName = HcsDidEventTargetName.DID_DOCUMENT; + + protected id: string; + protected type = HcsDidCreateDidDocumentEvent.DID_DOCUMENT_TYPE; + protected cid: string; + protected url: string; + + constructor(id: string, cid: string, url?: string) { + super(); + + if (!id || !cid) { + throw new DidError("Validation failed. DID Document args are missing"); + } + + if (!this.isDidValid(id)) { + throw new DidError("DID is invalid"); + } + + this.id = id; + this.cid = cid; + this.url = url; + } + + public getId() { + return this.id; + } + + public getType() { + return this.type; + } + + public getCid() { + return this.cid; + } + + public getUrl() { + return this.url; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + type: this.getType(), + cid: this.getCid(), + url: this.getUrl(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidCreateDidDocumentEvent { + return new HcsDidCreateDidDocumentEvent(tree?.id, tree?.cid, tree?.url); + } +} diff --git a/src/identity/hcs/did/event/document/hcs-did-delete-event.ts b/src/identity/hcs/did/event/document/hcs-did-delete-event.ts new file mode 100644 index 0000000..dbd977c --- /dev/null +++ b/src/identity/hcs/did/event/document/hcs-did-delete-event.ts @@ -0,0 +1,30 @@ +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; + +export class HcsDidDeleteEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.Document; + + constructor() { + super(); + } + + getId(): string { + return undefined; + } + + public toJsonTree() { + return null; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + public getBase64() { + return null; + } + + static fromJsonTree(tree: any): HcsDidDeleteEvent { + return new HcsDidDeleteEvent(); + } +} diff --git a/src/identity/hcs/did/event/hcs-did-event-parser.ts b/src/identity/hcs/did/event/hcs-did-event-parser.ts new file mode 100644 index 0000000..ef889f2 --- /dev/null +++ b/src/identity/hcs/did/event/hcs-did-event-parser.ts @@ -0,0 +1,56 @@ +import { Hashing } from "../../../../utils/hashing"; +import { DidMethodOperation } from "../../../did-method-operation"; +import { HcsDidCreateDidDocumentEvent } from "./document/hcs-did-create-did-document-event"; +import { HcsDidDeleteEvent } from "./document/hcs-did-delete-event"; +import { HcsDidEvent } from "./hcs-did-event"; +import { HcsDidEventTargetName } from "./hcs-did-event-target-name"; +import { HcsDidCreateDidOwnerEvent } from "./owner/hcs-did-create-did-owner-event"; +import { HcsDidUpdateDidOwnerEvent } from "./owner/hcs-did-update-did-owner-event"; +import { HcsDidCreateServiceEvent } from "./service/hcs-did-create-service-event"; +import { HcsDidRevokeServiceEvent } from "./service/hcs-did-revoke-service-event"; +import { HcsDidUpdateServiceEvent } from "./service/hcs-did-update-service-event"; +import { HcsDidCreateVerificationMethodEvent } from "./verification-method/hcs-did-create-verification-method-event"; +import { HcsDidRevokeVerificationMethodEvent } from "./verification-method/hcs-did-revoke-verification-method-event"; +import { HcsDidUpdateVerificationMethodEvent } from "./verification-method/hcs-did-update-verification-method-event"; +import { HcsDidCreateVerificationRelationshipEvent } from "./verification-relationship/hcs-did-create-verification-relationship-event"; +import { HcsDidRevokeVerificationRelationshipEvent } from "./verification-relationship/hcs-did-revoke-verification-relationship-event"; +import { HcsDidUpdateVerificationRelationshipEvent } from "./verification-relationship/hcs-did-update-verification-relationship-event"; + +const EVENT_NAME_TO_CLASS = { + [DidMethodOperation.CREATE]: { + [HcsDidEventTargetName.DID_OWNER]: HcsDidCreateDidOwnerEvent, + [HcsDidEventTargetName.DID_DOCUMENT]: HcsDidCreateDidDocumentEvent, + [HcsDidEventTargetName.SERVICE]: HcsDidCreateServiceEvent, + [HcsDidEventTargetName.VERIFICATION_METHOD]: HcsDidCreateVerificationMethodEvent, + [HcsDidEventTargetName.VERIFICATION_RELATIONSHIP]: HcsDidCreateVerificationRelationshipEvent, + }, + [DidMethodOperation.UPDATE]: { + [HcsDidEventTargetName.DID_OWNER]: HcsDidUpdateDidOwnerEvent, + [HcsDidEventTargetName.SERVICE]: HcsDidUpdateServiceEvent, + [HcsDidEventTargetName.VERIFICATION_METHOD]: HcsDidUpdateVerificationMethodEvent, + [HcsDidEventTargetName.VERIFICATION_RELATIONSHIP]: HcsDidUpdateVerificationRelationshipEvent, + }, + [DidMethodOperation.REVOKE]: { + [HcsDidEventTargetName.SERVICE]: HcsDidRevokeServiceEvent, + [HcsDidEventTargetName.VERIFICATION_METHOD]: HcsDidRevokeVerificationMethodEvent, + [HcsDidEventTargetName.VERIFICATION_RELATIONSHIP]: HcsDidRevokeVerificationRelationshipEvent, + }, +}; + +export class HcsDidEventParser { + static fromBase64(operation: DidMethodOperation, eventBase64: any): HcsDidEvent { + if (operation === DidMethodOperation.DELETE) { + return HcsDidDeleteEvent.fromJsonTree(null); + } + + try { + const tree = JSON.parse(Hashing.base64.decode(eventBase64)); + const eventsByOperation = EVENT_NAME_TO_CLASS[operation]; + const eventTargetName = Object.keys(eventsByOperation).find((etn) => !!tree[etn]); + + return eventsByOperation[eventTargetName].fromJsonTree(tree[eventTargetName]); + } catch { + return null; + } + } +} diff --git a/src/identity/hcs/did/event/hcs-did-event-target-name.ts b/src/identity/hcs/did/event/hcs-did-event-target-name.ts new file mode 100644 index 0000000..7427e20 --- /dev/null +++ b/src/identity/hcs/did/event/hcs-did-event-target-name.ts @@ -0,0 +1,8 @@ +export enum HcsDidEventTargetName { + DID_DOCUMENT = "DIDDocument", + DID_OWNER = "DIDOwner", + VERIFICATION_METHOD = "VerificationMethod", + VERIFICATION_RELATIONSHIP = "VerificationRelationship", + SERVICE = "Service", + Document = "Document", +} diff --git a/src/identity/hcs/did/event/hcs-did-event.ts b/src/identity/hcs/did/event/hcs-did-event.ts new file mode 100644 index 0000000..9ecaf3a --- /dev/null +++ b/src/identity/hcs/did/event/hcs-did-event.ts @@ -0,0 +1,74 @@ +import { Hashing } from "../../../../utils/hashing"; +import { HcsDid } from "../hcs-did"; +import { HcsDidEventTargetName } from "./hcs-did-event-target-name"; + +export abstract class HcsDidEvent { + protected SERVICE_ID_POSTFIX_REGEX = /^(service)\-[0-9]{1,}$/; + protected KEY_ID_POSTFIX_REGEX = /^(key)\-[0-9]{1,}$/; + protected OWNER_KEY_POSTFIX_REGEX = /^(did\-root\-key)$/; + + public abstract readonly targetName: HcsDidEventTargetName; + + constructor() {} + + abstract getId(): string; + + abstract toJsonTree(): any; + + abstract toJSON(): string; + + public getBase64() { + return Hashing.base64.encode(this.toJSON()); + } + + static fromJsonTree(tree: any): HcsDidEvent { + throw new Error("not implemented"); + } + + protected isDidValid(eventId: string) { + const [identifier, id] = eventId?.split("#"); + + if (!identifier) { + return false; + } + + HcsDid.parseIdentifier(identifier); + return true; + } + + protected isOwnerEventIdValid(eventId: string) { + const [identifier, id] = eventId?.split("#"); + + if (!identifier || !id) { + return false; + } + + HcsDid.parseIdentifier(identifier); + + return this.OWNER_KEY_POSTFIX_REGEX.test(id) !== false; + } + + protected isServiceEventIdValid(eventId: string) { + const [identifier, id] = eventId?.split("#"); + + if (!identifier || !id) { + return false; + } + + HcsDid.parseIdentifier(identifier); + + return this.SERVICE_ID_POSTFIX_REGEX.test(id) !== false; + } + + protected isKeyEventIdValid(eventId: string) { + const [identifier, id] = eventId?.split("#"); + + if (!identifier || !id) { + return false; + } + + HcsDid.parseIdentifier(identifier); + + return this.KEY_ID_POSTFIX_REGEX.test(id) !== false; + } +} diff --git a/src/identity/hcs/did/event/owner/hcs-did-create-did-owner-event.ts b/src/identity/hcs/did/event/owner/hcs-did-create-did-owner-event.ts new file mode 100644 index 0000000..b3b0ada --- /dev/null +++ b/src/identity/hcs/did/event/owner/hcs-did-create-did-owner-event.ts @@ -0,0 +1,81 @@ +import { PublicKey } from "@hashgraph/sdk"; +import { Hashing } from "../../../../../utils/hashing"; +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; + +export class HcsDidCreateDidOwnerEvent extends HcsDidEvent { + public static KEY_TYPE = "Ed25519VerificationKey2018"; + + public readonly targetName = HcsDidEventTargetName.DID_OWNER; + + protected id: string; + protected type = HcsDidCreateDidOwnerEvent.KEY_TYPE; + protected controller: string; + protected publicKey: PublicKey; + + constructor(id: string, controller: string, publicKey: PublicKey) { + super(); + + if (!id || !controller || !publicKey) { + throw new DidError("Validation failed. DID Owner args are missing"); + } + + if (!this.isOwnerEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#did-root-key"); + } + + this.id = id; + this.controller = controller; + this.publicKey = publicKey; + } + + public getId() { + return this.id; + } + + public getType() { + return this.type; + } + + public getController() { + return this.controller; + } + + public getPublicKey() { + return this.publicKey; + } + + public getPublicKeyBase58() { + return Hashing.base58.encode(this.getPublicKey().toBytes()); + } + + public getOwnerDef() { + return { + id: this.getId(), + type: this.getType(), + controller: this.getController(), + publicKeyBase58: this.getPublicKeyBase58(), + }; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + type: this.getType(), + controller: this.getController(), + publicKeyBase58: this.getPublicKeyBase58(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidCreateDidOwnerEvent { + const publicKey = PublicKey.fromBytes(Hashing.base58.decode(tree?.publicKeyBase58)); + return new HcsDidCreateDidOwnerEvent(tree?.id, tree?.controller, publicKey); + } +} diff --git a/src/identity/hcs/did/event/owner/hcs-did-update-did-owner-event.ts b/src/identity/hcs/did/event/owner/hcs-did-update-did-owner-event.ts new file mode 100644 index 0000000..84ac82f --- /dev/null +++ b/src/identity/hcs/did/event/owner/hcs-did-update-did-owner-event.ts @@ -0,0 +1,10 @@ +import { PublicKey } from "@hashgraph/sdk"; +import { Hashing } from "../../../../../utils/hashing"; +import { HcsDidCreateDidOwnerEvent } from "./hcs-did-create-did-owner-event"; + +export class HcsDidUpdateDidOwnerEvent extends HcsDidCreateDidOwnerEvent { + static fromJsonTree(tree: any): HcsDidUpdateDidOwnerEvent { + const publicKey = PublicKey.fromBytes(Hashing.base58.decode(tree?.publicKeyBase58)); + return new HcsDidUpdateDidOwnerEvent(tree?.id, tree?.controller, publicKey); + } +} diff --git a/src/identity/hcs/did/event/service/hcs-did-create-service-event.ts b/src/identity/hcs/did/event/service/hcs-did-create-service-event.ts new file mode 100644 index 0000000..ff3261e --- /dev/null +++ b/src/identity/hcs/did/event/service/hcs-did-create-service-event.ts @@ -0,0 +1,66 @@ +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; +import { ServiceTypes } from "./types"; + +export class HcsDidCreateServiceEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.SERVICE; + + protected id: string; + protected type: ServiceTypes; + protected serviceEndpoint: string; + + constructor(id: string, type: ServiceTypes, serviceEndpoint: string) { + super(); + + if (!id || !type || !serviceEndpoint) { + throw new DidError("Validation failed. Services args are missing"); + } + + if (!this.isServiceEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#service-{integer}"); + } + + this.id = id; + this.type = type; + this.serviceEndpoint = serviceEndpoint; + } + + public getId() { + return this.id; + } + + public getType() { + return this.type; + } + + public getServiceEndpoint() { + return this.serviceEndpoint; + } + + public getServiceDef() { + return { + id: this.getId(), + type: this.getType(), + serviceEndpoint: this.getServiceEndpoint(), + }; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + type: this.getType(), + serviceEndpoint: this.getServiceEndpoint(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidCreateServiceEvent { + return new HcsDidCreateServiceEvent(tree?.id, tree?.type, tree?.serviceEndpoint); + } +} diff --git a/src/identity/hcs/did/event/service/hcs-did-revoke-service-event.ts b/src/identity/hcs/did/event/service/hcs-did-revoke-service-event.ts new file mode 100644 index 0000000..5eb79ef --- /dev/null +++ b/src/identity/hcs/did/event/service/hcs-did-revoke-service-event.ts @@ -0,0 +1,43 @@ +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; + +export class HcsDidRevokeServiceEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.SERVICE; + + protected id: string; + + constructor(id: string) { + super(); + + if (!id) { + throw new DidError("Validation failed. Services args are missing"); + } + + if (!this.isServiceEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#service-{integer}"); + } + + this.id = id; + } + + public getId() { + return this.id; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidRevokeServiceEvent { + return new HcsDidRevokeServiceEvent(tree?.id); + } +} diff --git a/src/identity/hcs/did/event/service/hcs-did-update-service-event.ts b/src/identity/hcs/did/event/service/hcs-did-update-service-event.ts new file mode 100644 index 0000000..8348359 --- /dev/null +++ b/src/identity/hcs/did/event/service/hcs-did-update-service-event.ts @@ -0,0 +1,7 @@ +import { HcsDidCreateServiceEvent } from "./hcs-did-create-service-event"; + +export class HcsDidUpdateServiceEvent extends HcsDidCreateServiceEvent { + static fromJsonTree(tree: any): HcsDidCreateServiceEvent { + return new HcsDidUpdateServiceEvent(tree?.id, tree?.type, tree?.serviceEndpoint); + } +} diff --git a/src/identity/hcs/did/event/service/types.ts b/src/identity/hcs/did/event/service/types.ts new file mode 100644 index 0000000..c0b9a46 --- /dev/null +++ b/src/identity/hcs/did/event/service/types.ts @@ -0,0 +1 @@ +export type ServiceTypes = "LinkedDomains" | "DIDCommMessaging"; diff --git a/src/identity/hcs/did/event/verification-method/hcs-did-create-verification-method-event.ts b/src/identity/hcs/did/event/verification-method/hcs-did-create-verification-method-event.ts new file mode 100644 index 0000000..0c0473b --- /dev/null +++ b/src/identity/hcs/did/event/verification-method/hcs-did-create-verification-method-event.ts @@ -0,0 +1,81 @@ +import { PublicKey } from "@hashgraph/sdk"; +import { Hashing } from "../../../../../utils/hashing"; +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; +import { VerificationMethodSupportedKeyType } from "./types"; + +export class HcsDidCreateVerificationMethodEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.VERIFICATION_METHOD; + + protected id: string; + protected type: VerificationMethodSupportedKeyType; + protected controller: string; + protected publicKey: PublicKey; + + constructor(id: string, type: VerificationMethodSupportedKeyType, controller: string, publicKey: PublicKey) { + super(); + + if (!id || !type || !controller || !publicKey) { + throw new DidError("Validation failed. Verification Method args are missing"); + } + + if (!this.isKeyEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#key-{integer}"); + } + + this.id = id; + this.type = type; + this.controller = controller; + this.publicKey = publicKey; + } + + public getId() { + return this.id; + } + + public getType() { + return this.type; + } + + public getController() { + return this.controller; + } + + public getPublicKey() { + return this.publicKey; + } + + public getPublicKeyBase58() { + return Hashing.base58.encode(this.getPublicKey().toBytes()); + } + + public getVerificationMethodDef() { + return { + id: this.getId(), + type: this.getType(), + controller: this.getController(), + publicKeyBase58: this.getPublicKeyBase58(), + }; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + type: this.getType(), + controller: this.getController(), + publicKeyBase58: this.getPublicKeyBase58(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidCreateVerificationMethodEvent { + const publicKey = PublicKey.fromBytes(Hashing.base58.decode(tree?.publicKeyBase58)); + return new HcsDidCreateVerificationMethodEvent(tree?.id, tree?.type, tree?.controller, publicKey); + } +} diff --git a/src/identity/hcs/did/event/verification-method/hcs-did-revoke-verification-method-event.ts b/src/identity/hcs/did/event/verification-method/hcs-did-revoke-verification-method-event.ts new file mode 100644 index 0000000..f422db0 --- /dev/null +++ b/src/identity/hcs/did/event/verification-method/hcs-did-revoke-verification-method-event.ts @@ -0,0 +1,43 @@ +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; + +export class HcsDidRevokeVerificationMethodEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.VERIFICATION_METHOD; + + protected id: string; + + constructor(id: string) { + super(); + + if (!id) { + throw new DidError("Validation failed. Verification Method args are missing"); + } + + if (!this.isKeyEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#key-{integer}"); + } + + this.id = id; + } + + public getId() { + return this.id; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidRevokeVerificationMethodEvent { + return new HcsDidRevokeVerificationMethodEvent(tree?.id); + } +} diff --git a/src/identity/hcs/did/event/verification-method/hcs-did-update-verification-method-event.ts b/src/identity/hcs/did/event/verification-method/hcs-did-update-verification-method-event.ts new file mode 100644 index 0000000..e93b4bd --- /dev/null +++ b/src/identity/hcs/did/event/verification-method/hcs-did-update-verification-method-event.ts @@ -0,0 +1,10 @@ +import { PublicKey } from "@hashgraph/sdk"; +import { Hashing } from "../../../../../utils/hashing"; +import { HcsDidCreateVerificationMethodEvent } from "./hcs-did-create-verification-method-event"; + +export class HcsDidUpdateVerificationMethodEvent extends HcsDidCreateVerificationMethodEvent { + static fromJsonTree(tree: any): HcsDidCreateVerificationMethodEvent { + const publicKey = PublicKey.fromBytes(Hashing.base58.decode(tree?.publicKeyBase58)); + return new HcsDidUpdateVerificationMethodEvent(tree?.id, tree?.type, tree?.controller, publicKey); + } +} diff --git a/src/identity/hcs/did/event/verification-method/types.ts b/src/identity/hcs/did/event/verification-method/types.ts new file mode 100644 index 0000000..e7462c5 --- /dev/null +++ b/src/identity/hcs/did/event/verification-method/types.ts @@ -0,0 +1 @@ +export type VerificationMethodSupportedKeyType = "Ed25519VerificationKey2018"; diff --git a/src/identity/hcs/did/event/verification-relationship/hcs-did-create-verification-relationship-event.ts b/src/identity/hcs/did/event/verification-relationship/hcs-did-create-verification-relationship-event.ts new file mode 100644 index 0000000..2346b3e --- /dev/null +++ b/src/identity/hcs/did/event/verification-relationship/hcs-did-create-verification-relationship-event.ts @@ -0,0 +1,100 @@ +import { PublicKey } from "@hashgraph/sdk"; +import { Hashing } from "../../../../../utils/hashing"; +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; +import { VerificationRelationshipSupportedKeyType, VerificationRelationshipType } from "./types"; + +export class HcsDidCreateVerificationRelationshipEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.VERIFICATION_RELATIONSHIP; + + protected id: string; + protected type: VerificationRelationshipSupportedKeyType = "Ed25519VerificationKey2018"; + protected relationshipType: VerificationRelationshipType; + protected controller: string; + protected publicKey: PublicKey; + + constructor( + id: string, + relationshipType: VerificationRelationshipType, + type: VerificationRelationshipSupportedKeyType, + controller: string, + publicKey: PublicKey + ) { + super(); + + if (!id || !relationshipType || !type || !controller || !publicKey) { + throw new DidError("Validation failed. Verification Relationship args are missing"); + } + + if (!this.isKeyEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#key-{integer}"); + } + + this.id = id; + this.type = type; + this.relationshipType = relationshipType; + this.controller = controller; + this.publicKey = publicKey; + } + + public getId() { + return this.id; + } + + public getType() { + return this.type; + } + + public getRelationshipType() { + return this.relationshipType; + } + + public getController() { + return this.controller; + } + + public getPublicKey() { + return this.publicKey; + } + + public getPublicKeyBase58() { + return Hashing.base58.encode(this.getPublicKey().toBytes()); + } + + public getVerificationMethodDef() { + return { + id: this.getId(), + type: this.getType(), + controller: this.getController(), + publicKeyBase58: this.getPublicKeyBase58(), + }; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + relationshipType: this.getRelationshipType(), + type: this.getType(), + controller: this.getController(), + publicKeyBase58: this.getPublicKeyBase58(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidCreateVerificationRelationshipEvent { + const publicKey = PublicKey.fromBytes(Hashing.base58.decode(tree?.publicKeyBase58)); + return new HcsDidCreateVerificationRelationshipEvent( + tree?.id, + tree?.relationshipType, + tree?.type, + tree?.controller, + publicKey + ); + } +} diff --git a/src/identity/hcs/did/event/verification-relationship/hcs-did-revoke-verification-relationship-event.ts b/src/identity/hcs/did/event/verification-relationship/hcs-did-revoke-verification-relationship-event.ts new file mode 100644 index 0000000..580635f --- /dev/null +++ b/src/identity/hcs/did/event/verification-relationship/hcs-did-revoke-verification-relationship-event.ts @@ -0,0 +1,51 @@ +import { DidError } from "../../../../did-error"; +import { HcsDidEvent } from "../hcs-did-event"; +import { HcsDidEventTargetName } from "../hcs-did-event-target-name"; +import { VerificationRelationshipType } from "./types"; + +export class HcsDidRevokeVerificationRelationshipEvent extends HcsDidEvent { + public readonly targetName = HcsDidEventTargetName.VERIFICATION_RELATIONSHIP; + + protected id: string; + protected relationshipType: VerificationRelationshipType; + + constructor(id: string, relationshipType: VerificationRelationshipType) { + super(); + + if (!id || !relationshipType) { + throw new DidError("Validation failed. Verification Relationship args are missing"); + } + + if (!this.isKeyEventIdValid(id)) { + throw new DidError("Event ID is invalid. Expected format: {did}#key-{integer}"); + } + + this.id = id; + this.relationshipType = relationshipType; + } + + public getId() { + return this.id; + } + + public getRelationshipType() { + return this.relationshipType; + } + + public toJsonTree() { + return { + [this.targetName]: { + id: this.getId(), + relationshipType: this.getRelationshipType(), + }, + }; + } + + public toJSON() { + return JSON.stringify(this.toJsonTree()); + } + + static fromJsonTree(tree: any): HcsDidRevokeVerificationRelationshipEvent { + return new HcsDidRevokeVerificationRelationshipEvent(tree?.id, tree?.relationshipType); + } +} diff --git a/src/identity/hcs/did/event/verification-relationship/hcs-did-update-verification-relationship-event.ts b/src/identity/hcs/did/event/verification-relationship/hcs-did-update-verification-relationship-event.ts new file mode 100644 index 0000000..844ca10 --- /dev/null +++ b/src/identity/hcs/did/event/verification-relationship/hcs-did-update-verification-relationship-event.ts @@ -0,0 +1,16 @@ +import { PublicKey } from "@hashgraph/sdk"; +import { Hashing } from "../../../../../utils/hashing"; +import { HcsDidCreateVerificationRelationshipEvent } from "./hcs-did-create-verification-relationship-event"; + +export class HcsDidUpdateVerificationRelationshipEvent extends HcsDidCreateVerificationRelationshipEvent { + static fromJsonTree(tree: any): HcsDidUpdateVerificationRelationshipEvent { + const publicKey = PublicKey.fromBytes(Hashing.base58.decode(tree?.publicKeyBase58)); + return new HcsDidUpdateVerificationRelationshipEvent( + tree?.id, + tree?.relationshipType, + tree?.type, + tree?.controller, + publicKey + ); + } +} diff --git a/src/identity/hcs/did/event/verification-relationship/types.ts b/src/identity/hcs/did/event/verification-relationship/types.ts new file mode 100644 index 0000000..a5461ee --- /dev/null +++ b/src/identity/hcs/did/event/verification-relationship/types.ts @@ -0,0 +1,8 @@ +export type VerificationRelationshipType = + | "authentication" + | "assertionMethod" + | "keyAgreement" + | "capabilityInvocation" + | "capabilityDelegation"; + +export type VerificationRelationshipSupportedKeyType = "Ed25519VerificationKey2018"; diff --git a/src/identity/hcs/did/hcs-did-event-message-resolver.ts b/src/identity/hcs/did/hcs-did-event-message-resolver.ts new file mode 100644 index 0000000..7e50532 --- /dev/null +++ b/src/identity/hcs/did/hcs-did-event-message-resolver.ts @@ -0,0 +1,161 @@ +import { Client, Timestamp, TopicId } from "@hashgraph/sdk"; +import Long from "long"; +import { Validator } from "../../../utils/validator"; +import { MessageEnvelope } from "../message-envelope"; +import { HcsDidMessage } from "./hcs-did-message"; +import { HcsDidTopicListener } from "./hcs-did-topic-listener"; + +/** + * Resolves the DID Events from Hedera network. + */ +export class HcsDidEventMessageResolver { + /** + * Default time to wait before finishing resolution and after the last message was received. + */ + public static DEFAULT_TIMEOUT: Long = Long.fromInt(30000); + + protected topicId: TopicId; + protected messages: MessageEnvelope[] = []; + + private lastMessageArrivalTime: Long; + private nextMessageArrivalTimeout; + private resultsHandler: (input: MessageEnvelope[]) => void; + private errorHandler: (input: Error) => void; + private existingSignatures: string[]; + private readonly listener: HcsDidTopicListener; + private noMoreMessagesTimeout: Long; + + /** + * Instantiates a new DID resolver for the given DID topic. + * + * @param topicId The HCS DID topic ID. + */ + constructor(topicId: TopicId, startTime: Timestamp = new Timestamp(0, 0)) { + this.topicId = topicId; + this.listener = new HcsDidTopicListener(this.topicId, startTime); + + this.noMoreMessagesTimeout = HcsDidEventMessageResolver.DEFAULT_TIMEOUT; + this.lastMessageArrivalTime = Long.fromInt(Date.now()); + } + + public execute(client: Client): void { + new Validator().checkValidationErrors("Resolver not executed: ", (v) => { + return this.validate(v); + }); + + this.existingSignatures = []; + + this.listener + .setEndTime(Timestamp.fromDate(new Date())) + .setIgnoreErrors(false) + .onError(this.errorHandler) + .onComplete(() => this.finish()) + .subscribe(client, (msg) => { + return this.handleMessage(msg); + }); + + this.lastMessageArrivalTime = Long.fromInt(Date.now()); + this.waitOrFinish(); + } + + /** + * Handles incoming DID messages from DID Topic on a mirror node. + * + * @param envelope The parsed message envelope in a PLAIN mode. + */ + private handleMessage(envelope: MessageEnvelope): void { + this.lastMessageArrivalTime = Long.fromInt(Date.now()); + + if (!this.matchesSearchCriteria(envelope.open())) { + return; + } + + if (this.existingSignatures.indexOf(envelope.getSignature()) != -1) { + return; + } + + this.existingSignatures.push(envelope.getSignature()); + this.messages.push(envelope); + } + + /** + * Waits for a new message from the topic for the configured amount of time. + */ + protected async waitOrFinish(): Promise { + const timeDiff = Long.fromInt(Date.now()).sub(this.lastMessageArrivalTime); + + if (timeDiff.lessThanOrEqual(this.noMoreMessagesTimeout)) { + if (this.nextMessageArrivalTimeout) { + clearTimeout(this.nextMessageArrivalTimeout); + } + this.nextMessageArrivalTimeout = setTimeout( + () => this.waitOrFinish(), + this.noMoreMessagesTimeout.sub(timeDiff).toNumber() + ); + return; + } + + await this.finish(); + } + + protected async finish(): Promise { + this.resultsHandler(this.messages); + + if (this.nextMessageArrivalTimeout) { + clearTimeout(this.nextMessageArrivalTimeout); + } + + if (this.listener) { + this.listener.unsubscribe(); + } + } + + /** + * Defines a handler for resolution results. + * This will be called when the resolution process is finished. + * + * @param handler The results handler. + * @return This resolver instance. + */ + public whenFinished(handler: (input: MessageEnvelope[]) => void): HcsDidEventMessageResolver { + this.resultsHandler = handler; + return this; + } + + /** + * Defines a handler for errors when they happen during resolution. + * + * @param handler The error handler. + * @return This resolver instance. + */ + public onError(handler: (input: Error) => void): HcsDidEventMessageResolver { + this.errorHandler = handler; + return this; + } + + /** + * Defines a maximum time in milliseconds to wait for new messages from the topic. + * Default is 30 seconds. + * + * @param timeout The timeout in milliseconds to wait for new messages from the topic. + * @return This resolver instance. + */ + public setTimeout(timeout: Long | number): HcsDidEventMessageResolver { + this.noMoreMessagesTimeout = Long.fromValue(timeout); + return this; + } + + /** + * Runs validation logic of the resolver's configuration. + * + * @param validator The errors validator. + */ + protected validate(validator: Validator): void { + validator.require(!!this.topicId, "Consensus topic ID not defined."); + validator.require(!!this.resultsHandler, "Results handler 'whenFinished' not defined."); + } + + protected matchesSearchCriteria(message: HcsDidMessage): boolean { + return true; + } +} diff --git a/src/identity/hcs/did/hcs-did-message.ts b/src/identity/hcs/did/hcs-did-message.ts index 2498a25..a565c8d 100644 --- a/src/identity/hcs/did/hcs-did-message.ts +++ b/src/identity/hcs/did/hcs-did-message.ts @@ -1,46 +1,41 @@ -import { PublicKey, Timestamp, TopicId } from "@hashgraph/sdk"; -import { Hashing } from "../../../utils/hashing"; +import { Timestamp, TopicId } from "@hashgraph/sdk"; +import Long from "long"; import { TimestampUtils } from "../../../utils/timestamp-utils"; -import { DidDocumentBase } from "../../did-document-base"; -import { DidDocumentJsonProperties } from "../../did-document-json-properties"; import { DidMethodOperation } from "../../did-method-operation"; -import { Decrypter, Encrypter, Message } from "../message"; -import { MessageEnvelope } from "../message-envelope"; +import { DidParser } from "../../did-parser"; +import { HcsDidEvent } from "./event/hcs-did-event"; +import { HcsDidEventParser } from "./event/hcs-did-event-parser"; import { HcsDid } from "./hcs-did"; +export type Signer = (message: T) => T; + /** * The DID document message submitted to appnet's DID Topic. */ -export class HcsDidMessage extends Message { +export class HcsDidMessage { + private static serialVersionUID = Long.fromInt(1); + + protected timestamp: Timestamp; protected operation: DidMethodOperation; protected did: string; - protected didDocumentBase64: string; - /** - * The date when the DID was created and published. - * It is equal to consensus timestamp of the first creation message. - * This property is set by the listener and injected into the DID document upon calling getDidDocument() method. - */ - - protected created: Timestamp; - /** - * The date when the DID was updated and published. - * It is equal to consensus timestamp of the last valid update or delete message. - * This property is set by the listener and injected into the DID document upon calling getDidDocument() method. - */ - protected updated: Timestamp; + protected event: HcsDidEvent; /** * Creates a new instance of {@link HcsDidMessage}. * * @param operation The operation on DID document. * @param did The DID string. - * @param didDocumentBase64 The Base64-encoded DID document. + * @param event The DID Event. */ - constructor(operation: DidMethodOperation, did: string, didDocumentBase64: string) { - super(); + constructor(operation: DidMethodOperation, did: string, event: HcsDidEvent) { + this.timestamp = TimestampUtils.now(); this.operation = operation; this.did = did; - this.didDocumentBase64 = didDocumentBase64; + this.event = event; + } + + public getTimestamp(): Timestamp { + return this.timestamp; } public getOperation(): DidMethodOperation { @@ -51,103 +46,34 @@ export class HcsDidMessage extends Message { return this.did; } - public getDidDocumentBase64(): string { - return this.didDocumentBase64; - } - - public getCreated(): Timestamp { - return this.created; - } - - public getUpdated(): Timestamp { - return this.updated; - } - - public setUpdated(updated: Timestamp): void { - this.updated = updated; + public getEvent(): HcsDidEvent { + return this.event; } - public setCreated(created: Timestamp): void { - this.created = created; - } - - /** - * Decodes didDocumentBase64 field and returns its content. - * In case this message is in encrypted mode, it will return encrypted content, - * so getPlainDidDocument method should be used instead. - * If message consensus timestamps for creation and update are provided they will be injected into the result - * document upon decoding. - * - * @return The decoded DID document as JSON string. - */ - public getDidDocument(): string { - if (this.didDocumentBase64 == null) { - return null; - } - - let document: string = Hashing.base64.decode(this.didDocumentBase64); - - // inject timestamps - if (this.created != null || this.updated != null) { - const root = JSON.parse(document); - if (this.created != null) { - root[DidDocumentJsonProperties.CREATED] = TimestampUtils.toJSON(this.created); - } - - if (this.updated != null) { - root[DidDocumentJsonProperties.UPDATED] = TimestampUtils.toJSON(this.updated); - } - document = JSON.stringify(root); - } - - return document; + public getEventBase64() { + return this.getEvent().getBase64(); } - /** - * Validates this DID message by checking its completeness, signature and DID document. - * - * @return True if the message is valid, false otherwise. - */ - public isValid(): boolean; /** * Validates this DID message by checking its completeness, signature and DID document. * * @param didTopicId The DID topic ID against which the message is validated. * @return True if the message is valid, false otherwise. */ + public isValid(): boolean; public isValid(didTopicId: TopicId): boolean; public isValid(...args: any[]): boolean { const didTopicId: TopicId = args[0] || null; - if (this.did == null || this.didDocumentBase64 == null) { + + if (this.did == null || this.event == null || this.operation == null) { return false; } try { - const doc: DidDocumentBase = DidDocumentBase.fromJson(this.getDidDocument()); - - // Validate if DID and DID document are present and match - if (this.did != doc.getId()) { - return false; - } - - // Validate if DID root key is present in the document - if (doc.getDidRootKey() == null || doc.getDidRootKey().getPublicKeyBase58() == null) { - return false; - } - - // Verify that DID was derived from this DID root key - const hcsDid: HcsDid = HcsDid.fromString(this.did); - - // Extract public key from the DID document - const publicKeyBytes: Uint8Array = Hashing.base58.decode(doc.getDidRootKey().getPublicKeyBase58()); - const publicKey: PublicKey = PublicKey.fromBytes(publicKeyBytes); - - if (HcsDid.publicKeyToIdString(publicKey) != hcsDid.getIdString()) { - return false; - } + const hcsDid: HcsDid = DidParser.parse(this.did); // Verify that the message was sent to the right topic, if the DID contains the topic - if (!!didTopicId && !!hcsDid.getDidTopicId() && (didTopicId.toString() != hcsDid.getDidTopicId().toString())) { + if (!!didTopicId && !!hcsDid.getTopicId() && didTopicId.toString() != hcsDid.getTopicId().toString()) { return false; } } catch (e) { @@ -157,45 +83,25 @@ export class HcsDidMessage extends Message { return true; } - /** - * Extracts #did-root-key from the DID document. - * - * @return Public key of the DID subject. - */ - public extractDidRootKey(): PublicKey { - let result: PublicKey = null; - try { - const doc: DidDocumentBase = DidDocumentBase.fromJson(this.getDidDocument()); - // Make sure that DID root key is present in the document - if (doc.getDidRootKey() != null && doc.getDidRootKey().getPublicKeyBase58() != null) { - const publicKeyBytes: Uint8Array = Hashing.base58.decode(doc.getDidRootKey().getPublicKeyBase58()); - result = PublicKey.fromBytes(publicKeyBytes); - } - // ArrayIndexOutOfBoundsException is thrown in case public key is invalid in PublicKey.fromBytes - } catch (e) { - return null; - } - - return result; - } - public toJsonTree(): any { - const result: any = super.toJsonTree(); + const result: any = { timestamp: TimestampUtils.toJSON(this.timestamp) }; result.operation = this.operation; result.did = this.did; - result.didDocumentBase64 = this.didDocumentBase64; + result.event = this.getEventBase64(); return result; } public static fromJsonTree(tree: any, result?: HcsDidMessage): HcsDidMessage { + const event = HcsDidEventParser.fromBase64(tree.operation, tree.event); + if (!result) { - result = new HcsDidMessage(tree.operation, tree.did, tree.didDocumentBase64); + result = new HcsDidMessage(tree.operation, tree.did, event); } else { result.operation = tree.operation; result.did = tree.did; - result.didDocumentBase64 = tree.didDocumentBase64; + result.event = event; } - result = super.fromJsonTree(tree, result) as HcsDidMessage; + result.timestamp = TimestampUtils.fromJson(tree.timestamp); return result; } @@ -203,71 +109,7 @@ export class HcsDidMessage extends Message { return JSON.stringify(this.toJsonTree()); } - public static fromJson(json: string): Message { - return Message.fromJsonTree(JSON.parse(json)); - } - - /** - * Creates a new DID message for submission to HCS topic. - * - * @param didDocumentJson DID document as JSON string. - * @param operation The operation on DID document. - * @return The HCS message wrapped in an envelope for the given DID document and method operation. - */ - public static fromDidDocumentJson(didDocumentJson: string, operation: DidMethodOperation): MessageEnvelope { - const didDocumentBase: DidDocumentBase = DidDocumentBase.fromJson(didDocumentJson); - const didDocumentBase64 = Hashing.base64.encode(didDocumentJson); - const message: HcsDidMessage = new HcsDidMessage(operation, didDocumentBase.getId(), didDocumentBase64); - return new MessageEnvelope(message); - } - - /** - * Provides an encryption operator that converts an {@link HcsDidMessage} into encrypted one. - * - * @param encryptionFunction The encryption function to use for encryption of single attributes. - * @return The encryption operator instance. - */ - public static getEncrypter(encryptionFunction: Encrypter): Encrypter { - if (encryptionFunction == null) { - throw "Encryption function is missing or null."; - } - return function (message: HcsDidMessage): HcsDidMessage { - const operation: DidMethodOperation = message.getOperation(); - // Encrypt the DID - const encryptedDid: string = encryptionFunction(message.getDid()); - const did: string = Hashing.base64.encode(encryptedDid); - // Encrypt the DID document - const encryptedDoc: string = encryptionFunction(message.getDidDocumentBase64()); - const didDocumentBase64: string = Hashing.base64.encode(encryptedDoc); - return new HcsDidMessage(operation, did, didDocumentBase64); - }; - } - - /** - * Provides a decryption function that converts {@link HcsDidMessage} in encrypted for into a plain form. - * - * @param decryptionFunction The decryption function to use for decryption of single attributes. - * @return The Decryption function for the {@link HcsDidMessage} - */ - public static getDecrypter(decryptionFunction: Decrypter): Decrypter { - if (decryptionFunction == null) { - throw "Decryption function is missing or null."; - } - return function (encryptedMsg: HcsDidMessage, consensusTimestamp: Timestamp): HcsDidMessage { - const operation: DidMethodOperation = encryptedMsg.getOperation(); - // Decrypt DID string - let decryptedDid: string = encryptedMsg.getDid(); - if (decryptedDid != null) { - const did: string = Hashing.base64.decode(decryptedDid); - decryptedDid = decryptionFunction(did, consensusTimestamp); - } - // Decrypt DID document - let decryptedDocBase64 = encryptedMsg.getDidDocumentBase64(); - if (decryptedDocBase64 != null) { - const doc: string = Hashing.base64.decode(decryptedDocBase64); - decryptedDocBase64 = decryptionFunction(doc, consensusTimestamp); - } - return new HcsDidMessage(operation, decryptedDid, decryptedDocBase64); - }; + public static fromJson(json: string): HcsDidMessage { + return HcsDidMessage.fromJsonTree(JSON.parse(json)); } } diff --git a/src/identity/hcs/did/hcs-did-resolver.ts b/src/identity/hcs/did/hcs-did-resolver.ts deleted file mode 100644 index 9755eca..0000000 --- a/src/identity/hcs/did/hcs-did-resolver.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { TopicId } from "@hashgraph/sdk"; -import { TimestampUtils } from "../../../utils/timestamp-utils"; -import { DidMethodOperation } from "../../did-method-operation"; -import { MessageEnvelope } from "../message-envelope"; -import { MessageListener } from "../message-listener"; -import { MessageResolver } from "../message-resolver"; -import { HcsDidMessage } from "./hcs-did-message"; -import { HcsDidTopicListener } from "./hcs-did-topic-listener"; - -/** - * Resolves the DID from Hedera network. - */ -export class HcsDidResolver extends MessageResolver { - /** - * Instantiates a new DID resolver for the given DID topic. - * - * @param topicId The HCS DID topic ID. - */ - constructor(topicId: TopicId) { - super(topicId); - } - - /** - * Adds a DID to resolve. - * - * @param did The DID string. - * @return This resolver instance. - */ - public addDid(did: string): HcsDidResolver { - if (did != null) { - this.results.set(did, null); - } - return this; - } - - /** - * Adds multiple DIDs to resolve. - * - * @param dids The set of DID strings. - * @return This resolver instance. - */ - public addDids(dids: string[]): HcsDidResolver { - if (dids) { - dids.forEach(d => this.addDid(d)); - } - return this; - } - - protected override matchesSearchCriteria(message: HcsDidMessage): boolean { - return this.results.has(message.getDid()); - } - - protected override processMessage(envelope: MessageEnvelope): void { - const message: HcsDidMessage = envelope.open(); - - // Also skip messages that are older than the once collected or if we already have a DELETE message - const existing: MessageEnvelope = this.results.get(message.getDid()); - - const chackOperation = ( - (existing != null) && - ( - (TimestampUtils.lessThan(envelope.getConsensusTimestamp(), existing.getConsensusTimestamp())) || - ( - DidMethodOperation.DELETE == (existing.open().getOperation()) && - DidMethodOperation.DELETE != (message.getOperation()) - ) - ) - ) - if (chackOperation) { - return; - } - - // Preserve created and updated timestamps - message.setUpdated(envelope.getConsensusTimestamp()); - if (DidMethodOperation.CREATE == message.getOperation()) { - message.setCreated(envelope.getConsensusTimestamp()); - } else if (existing != null) { - message.setCreated(existing.open().getCreated()); - } - - // Add valid message to the results - this.results.set(message.getDid(), envelope); - } - - protected override supplyMessageListener(): MessageListener { - return new HcsDidTopicListener(this.topicId); - } -} diff --git a/src/identity/hcs/did/hcs-did-root-key.ts b/src/identity/hcs/did/hcs-did-root-key.ts deleted file mode 100644 index e25928c..0000000 --- a/src/identity/hcs/did/hcs-did-root-key.ts +++ /dev/null @@ -1,103 +0,0 @@ -import {PublicKey} from "@hashgraph/sdk"; -import bs58 from "bs58"; -import {HcsDid} from "./hcs-did"; - -/** - * Represents a root key of HCS Identity DID. - * That is a public key of type Ed25519VerificationKey2018 compatible with a single publicKey entry of a DID Document. - */ -export class HcsDidRootKey { - public static DID_ROOT_KEY_NAME = '#did-root-key'; - public static DID_ROOT_KEY_TYPE = 'Ed25519VerificationKey2018'; - - private id: string; - private type: string; - private controller: string; - private publicKeyBase58: string; - - /** - * Creates a {@link HcsDidRootKey} object from the given {@link HcsDid} DID and it's root public key. - * - * @param did The {@link HcsDid} DID object. - * @param didRootKey The public key from which the DID was derived. - * @return The {@link HcsDidRootKey} object. - */ - public static fromHcsIdentity(did: HcsDid, didRootKey: PublicKey): HcsDidRootKey { - if (!did) { - throw new Error('DID cannot be ' + did); - } - if (!didRootKey) { - throw new Error('DID root key cannot be ' + didRootKey); - } - if (HcsDid.publicKeyToIdString(didRootKey) !== did.getIdString()) { - throw new Error('The specified DID does not correspond to the given DID root key'); - } - const result = new HcsDidRootKey(); - result.controller = did.toDid(); - result.id = result.controller + HcsDidRootKey.DID_ROOT_KEY_NAME; - result.publicKeyBase58 = bs58.encode(didRootKey.toBytes()); - result.type = HcsDidRootKey.DID_ROOT_KEY_TYPE; - - return result; - } - - public static fromId(id: string): HcsDidRootKey { - if (id == null) { - throw new Error("id cannot be null"); - } - const didString = id.replace(new RegExp(HcsDidRootKey.DID_ROOT_KEY_NAME + "$"), ""); - if (didString == null) { - throw new Error("DID cannot be null"); - } - const did = HcsDid.fromString(didString); - - const result = new HcsDidRootKey(); - result.controller = did.toDid(); - result.id = result.controller + this.DID_ROOT_KEY_NAME; - result.publicKeyBase58 = null; - result.type = this.DID_ROOT_KEY_TYPE; - return result; - } - - public getId(): string { - return this.id; - } - - public getType(): string { - return this.type; - } - - public getController(): string { - return this.controller; - } - - public getPublicKeyBase58(): string { - return this.publicKeyBase58; - } - - public toJsonTree(): any { - const result: any = {}; - result.id = this.id; - result.type = this.type; - result.controller = this.controller; - result.publicKeyBase58 = this.publicKeyBase58; - return result; - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - public static fromJsonTree(json: any): HcsDidRootKey { - const result = new HcsDidRootKey(); - result.id = json.id; - result.type = json.type; - result.controller = json.controller; - result.publicKeyBase58 = json.publicKeyBase58; - return result; - } - - public static fromJson(json: string): HcsDidRootKey { - return HcsDidRootKey.fromJsonTree(JSON.parse(json)); - } -} diff --git a/src/identity/hcs/did/hcs-did-topic-listener.ts b/src/identity/hcs/did/hcs-did-topic-listener.ts index 5b7c4d4..2d75765 100644 --- a/src/identity/hcs/did/hcs-did-topic-listener.ts +++ b/src/identity/hcs/did/hcs-did-topic-listener.ts @@ -1,24 +1,118 @@ -import { TopicId, TopicMessage } from "@hashgraph/sdk"; +import { Client, Timestamp, TopicId, TopicMessage, TopicMessageQuery } from "@hashgraph/sdk"; +import SubscriptionHandle from "@hashgraph/sdk/lib/topic/SubscriptionHandle"; +import { DidError } from "../../did-error"; import { MessageEnvelope } from "../message-envelope"; -import { MessageListener } from "../message-listener"; import { HcsDidMessage } from "./hcs-did-message"; /** * A listener of confirmed {@link HcsDidMessage} messages from a DID topic. * Messages are received from a given mirror node, parsed and validated. */ -export class HcsDidTopicListener extends MessageListener { +export class HcsDidTopicListener { + protected topicId: TopicId; + protected query: TopicMessageQuery; + protected errorHandler: (input: Error) => void; + protected ignoreErrors: boolean; + protected subscriptionHandle: SubscriptionHandle; + protected filters: ((input: TopicMessage) => boolean)[]; + protected invalidMessageHandler: (t: TopicMessage, u: string) => void; + /** * Creates a new instance of a DID topic listener for the given consensus topic. * By default, invalid messages are ignored and errors are not. * * @param didTopicId The DID consensus topic ID. */ - constructor(didTopicId: TopicId) { - super(didTopicId); + constructor(topicId: TopicId, startTime: Timestamp = new Timestamp(0, 0)) { + this.topicId = topicId; + this.query = new TopicMessageQuery().setTopicId(topicId).setStartTime(startTime); + + this.query.setMaxBackoff(2000); + this.query.setMaxAttempts(15); + + this.ignoreErrors = false; + } + + /** + * Adds a custom filter for topic responses from a mirror node. + * Messages that do not pass the test are skipped before any other checks are run. + * + * @param filter The filter function. + * @return This listener instance. + */ + public addFilter(filter: (input: TopicMessage) => boolean): HcsDidTopicListener { + if (!this.filters) { + this.filters = []; + } + this.filters.push(filter); + + return this; + } + + /** + * Subscribes to mirror node topic messages stream. + * + * @param client Mirror client instance. + * @param receiver Receiver of parsed messages. + * @return This listener instance. + */ + public subscribe(client: Client, receiver: (input: MessageEnvelope) => void): HcsDidTopicListener { + const errorHandler = (message: TopicMessage, error: Error) => { + this.handleError(error); + }; + const listener = (message: TopicMessage) => { + this.handleResponse(message, receiver); + }; + + this.subscriptionHandle = this.query.subscribe(client, errorHandler, listener); + + return this; + } + + /** + * Stops receiving messages from the topic. + */ + public unsubscribe(): void { + if (this.subscriptionHandle) { + this.subscriptionHandle.unsubscribe(); + } } - protected override extractMessage(response: TopicMessage): MessageEnvelope { + /** + * Handles incoming messages from the topic on a mirror node. + * + * @param response Response message coming from the mirror node for the topic. + * @param receiver Consumer of the result message. + */ + protected handleResponse(response: TopicMessage, receiver: (input: MessageEnvelope) => void) { + if (this.filters) { + for (let filter of this.filters) { + if (!filter(response)) { + this.reportInvalidMessage(response, "Message was rejected by external filter"); + return; + } + } + } + + const envelope = this.extractMessage(response); + + if (!envelope) { + this.reportInvalidMessage(response, "Extracting envelope from the mirror response failed"); + return; + } + + if (this.isMessageValid(envelope, response)) { + receiver(envelope); + } + } + + /** + * Extracts and parses the message inside the response object into the given type. + * + * @param response Response message coming from the mirror node for this listener's topic. + * @return The message inside an envelope. + */ + protected extractMessage(response: TopicMessage): MessageEnvelope { let result: MessageEnvelope = null; try { result = MessageEnvelope.fromMirrorResponse(response, HcsDidMessage); @@ -29,22 +123,21 @@ export class HcsDidTopicListener extends MessageListener { return result; } - protected override isMessageValid(envelope: MessageEnvelope, response: TopicMessage): boolean { + /** + * Validates the message and its envelope signature. + * + * @param message The message inside an envelope. + * @param response Response message coming from the mirror node for this listener's topic. + * @return True if the message is valid, False otherwise. + */ + protected isMessageValid(envelope: MessageEnvelope, response: TopicMessage): boolean { try { - const msgDecrypter = !!this.decrypter ? HcsDidMessage.getDecrypter(this.decrypter) : null; - - const message: HcsDidMessage = envelope.open(msgDecrypter); + const message: HcsDidMessage = envelope.open(); if (!message) { this.reportInvalidMessage(response, "Empty message received when opening envelope"); return false; } - const key = message.extractDidRootKey(); - if (!envelope.isSignatureValid(key)) { - this.reportInvalidMessage(response, "Signature validation failed"); - return false; - } - if (!message.isValid(this.topicId)) { this.reportInvalidMessage(response, "Message content validation failed."); return false; @@ -56,6 +149,83 @@ export class HcsDidTopicListener extends MessageListener { this.reportInvalidMessage(response, "Exception while validating message: " + err.message); return false; } + } + + /** + * Handles the given error internally. + * If external error handler is defined, passes the error there, otherwise raises RuntimeException or ignores it + * depending on a ignoreErrors flag. + * + * @param err The error. + * @throws RuntimeException Runtime exception with the given error in case external error handler is not defined + * and errors were not requested to be ignored. + */ + protected handleError(err: Error): void { + if (this.errorHandler) { + this.errorHandler(err); + } else if (!this.ignoreErrors) { + throw new DidError(err.message); + } + } + + /** + * Reports invalid message to the handler. + * + * @param response The mirror response. + * @param reason The reason why message validation failed. + */ + protected reportInvalidMessage(response: TopicMessage, reason: string): void { + if (this.invalidMessageHandler) { + this.invalidMessageHandler(response, reason); + } + } + + /** + * Defines a handler for errors when they happen during execution. + * + * @param handler The error handler. + * @return This transaction instance. + */ + public onError(handler: (input: Error) => void): HcsDidTopicListener { + this.errorHandler = handler; + return this; + } + + /** + * Defines a handler for invalid messages received from the topic. + * The first parameter of the handler is the mirror response. + * The second parameter is the reason why the message failed validation (if available). + * + * @param handler The invalid message handler. + * @return This transaction instance. + */ + public onInvalidMessageReceived(handler: (t: TopicMessage, u: string) => void): HcsDidTopicListener { + this.invalidMessageHandler = handler; + return this; + } + + public setStartTime(startTime: Timestamp): HcsDidTopicListener { + this.query.setStartTime(startTime); + return this; + } + + public setEndTime(endTime: Timestamp): HcsDidTopicListener { + this.query.setEndTime(endTime); + return this; + } + + public setLimit(messagesLimit: Long): HcsDidTopicListener { + this.query.setLimit(messagesLimit); + return this; + } + + public setIgnoreErrors(ignoreErrors: boolean): HcsDidTopicListener { + this.ignoreErrors = ignoreErrors; + return this; + } + public onComplete(handler: () => void) { + this.query.setCompletionHandler(handler); + return this; } } diff --git a/src/identity/hcs/did/hcs-did-transaction.ts b/src/identity/hcs/did/hcs-did-transaction.ts index 9e8b82b..fff096b 100644 --- a/src/identity/hcs/did/hcs-did-transaction.ts +++ b/src/identity/hcs/did/hcs-did-transaction.ts @@ -1,20 +1,28 @@ -import {MessageTransaction} from "../message-transaction"; -import {HcsDidMessage} from "./hcs-did-message"; -import {DidMethodOperation} from "../../did-method-operation"; -import {PublicKey, TopicId} from "@hashgraph/sdk"; -import {MessageEnvelope} from "../message-envelope"; -import {Validator} from "../../../utils/validator"; -import {MessageListener} from "../message-listener"; -import {HcsDidTopicListener} from "./hcs-did-topic-listener"; -import {Encrypter} from "../message"; +import { Client, Timestamp, TopicId, TopicMessageSubmitTransaction, Transaction, TransactionId } from "@hashgraph/sdk"; +import moment from "moment"; +import { ArraysUtils } from "../../../utils/arrays-utils"; +import { Validator } from "../../../utils/validator"; +import { DidError } from "../../did-error"; +import { MessageEnvelope } from "../message-envelope"; +import { HcsDidMessage, Signer } from "./hcs-did-message"; +import { HcsDidTopicListener } from "./hcs-did-topic-listener"; /** * The DID document creation, update or deletion transaction. * Builds a correct {@link HcsDidMessage} and send it to HCS DID topic. */ -export class HcsDidTransaction extends MessageTransaction { - private operation: DidMethodOperation; - private didDocument: string; +export class HcsDidTransaction { + private static SUBTRACT_TIME = 1; // seconds + + protected topicId: TopicId; + protected message: MessageEnvelope; + + private buildTransactionFunction: (input: TopicMessageSubmitTransaction) => Promise; + private receiver: (input: MessageEnvelope) => void; + private errorHandler: (input: Error) => void; + private executed: boolean; + private signer: Signer; + private listener: HcsDidTopicListener; /** * Instantiates a new transaction object from a message that was already prepared. @@ -22,59 +30,163 @@ export class HcsDidTransaction extends MessageTransaction { * @param topicId The HCS DID topic ID where message will be submitted. * @param message The message envelope. */ - constructor(message: MessageEnvelope, topicId: TopicId); + constructor(message: MessageEnvelope, topicId: TopicId) { + if (message instanceof MessageEnvelope && topicId instanceof TopicId) { + this.topicId = topicId; + this.message = message; + this.executed = false; + } else { + throw new DidError("Invalid arguments"); + } + } + + /** + * Provides a {@link MessageListener} instance specific to the submitted message type. + * + * @param topicIdToListen ID of the HCS topic. + * @return The topic listener for this message on a mirror node. + */ + protected provideTopicListener(topicIdToListen: TopicId): HcsDidTopicListener { + return new HcsDidTopicListener(topicIdToListen); + } /** - * Instantiates a new transaction object. + * Handles the error. + * If external error handler is defined, passes the error there, otherwise raises RuntimeException. * - * @param operation The operation to be performed on a DID document. - * @param topicId The HCS DID topic ID where message will be submitted. + * @param err The error. + * @throws RuntimeException Runtime exception with the given error in case external error handler is not defined. */ - constructor(operation: DidMethodOperation, topicId: TopicId); - constructor(...args) { - if ( - (args[0] instanceof MessageEnvelope) && - (args[1] instanceof TopicId) && - (args.length === 2) - ) { - const [message, topicId] = args; - super(topicId, message); - this.operation = null; - } else if (args.length === 2) { - const [operation, topicId] = args; - super(topicId); - this.operation = operation; + protected handleError(err: Error): void { + if (this.errorHandler) { + this.errorHandler(err); } else { - throw new Error('Invalid arguments') + throw new DidError(err.message); } } /** - * Sets a DID document as JSON string that will be submitted to HCS. + * Handles event from a mirror node when a message was consensus was reached and message received. * - * @param didDocument The didDocument to be published. + * @param receiver The receiver handling incoming message. * @return This transaction instance. */ - public setDidDocument(didDocument: string): HcsDidTransaction { - this.didDocument = didDocument; + public onMessageConfirmed(receiver: (input: MessageEnvelope) => void): HcsDidTransaction { + this.receiver = receiver; return this; } - protected validate(validator: Validator): void { - super.validate(validator); - validator.require(!!this.didDocument || !!this.message, 'DID document is mandatory.'); - validator.require(!!this.operation || !!this.message, 'DID method operation is not defined.'); + /** + * Defines a handler for errors when they happen during execution. + * + * @param handler The error handler. + * @return This transaction instance. + */ + public onError(handler: (input: Error) => void): HcsDidTransaction { + this.errorHandler = handler; + return this; } - protected buildMessage(): MessageEnvelope { - return HcsDidMessage.fromDidDocumentJson(this.didDocument, this.operation); + /** + * Defines a function that signs the message. + * + * @param signer The signing function to set. + * @return This transaction instance. + */ + public signMessage(signer: Signer): HcsDidTransaction { + this.signer = signer; + return this; } - protected provideTopicListener(topicIdToListen: TopicId): MessageListener { - return new HcsDidTopicListener(topicIdToListen); + /** + * Sets {@link TopicMessageSubmitTransaction} parameters, builds and signs it without executing it. + * Topic ID and transaction message content are already set in the incoming transaction. + * + * @param builderFunction The transaction builder function. + * @return This transaction instance. + */ + public buildAndSignTransaction( + builderFunction: (input: TopicMessageSubmitTransaction) => Promise + ): HcsDidTransaction { + this.buildTransactionFunction = builderFunction; + return this; + } + + /** + * Builds the message and submits it to appnet's topic. + * + * @param client The hedera network client. + * @return Transaction ID. + */ + public async execute(client: Client): Promise { + new Validator().checkValidationErrors("MessageTransaction execution failed: ", (v) => { + return this.validate(v); + }); + + const envelope = this.message; + + const messageContent = !envelope.getSignature() + ? envelope.sign(this.signer) + : ArraysUtils.fromString(envelope.toJSON()); + + if (this.receiver) { + this.listener = this.provideTopicListener(this.topicId); + this.listener + .setStartTime( + Timestamp.fromDate(moment().subtract(HcsDidTransaction.SUBTRACT_TIME, "seconds").toDate()) + ) + .setIgnoreErrors(false) + .addFilter((response) => { + return ArraysUtils.equals(messageContent, response.contents); + }) + .onError((err) => { + return this.handleError(err); + }) + .onInvalidMessageReceived((response, reason) => { + if (!ArraysUtils.equals(messageContent, response.contents)) { + return; + } + + this.handleError(new DidError(reason + ": " + ArraysUtils.toString(response.contents))); + this.listener.unsubscribe(); + }) + .subscribe(client, (msg) => { + this.listener.unsubscribe(); + this.receiver(msg); + }); + } + + const tx = new TopicMessageSubmitTransaction().setTopicId(this.topicId).setMessage(messageContent); + + let transactionId; + + try { + const response = await (await this.buildTransactionFunction(tx)).execute(client); + await response.getReceipt(client); + + transactionId = response.transactionId; + this.executed = true; + } catch (e) { + this.handleError(e); + if (this.listener) { + this.listener.unsubscribe(); + } + } + + return transactionId; } - protected provideMessageEncrypter(encryptionFunction: Encrypter): (input: HcsDidMessage) => HcsDidMessage { - return HcsDidMessage.getEncrypter(encryptionFunction); + /** + * Runs validation logic. + * + * @param validator The errors validator. + */ + protected validate(validator: Validator): void { + validator.require(!this.executed, "This transaction has already been executed."); + validator.require( + !!this.signer || (!!this.message && !!this.message.getSignature()), + "Signing function is missing." + ); + validator.require(!!this.buildTransactionFunction, "Transaction builder is missing."); } } diff --git a/src/identity/hcs/did/hcs-did.ts b/src/identity/hcs/did/hcs-did.ts index 87208fc..bdac3ae 100644 --- a/src/identity/hcs/did/hcs-did.ts +++ b/src/identity/hcs/did/hcs-did.ts @@ -1,337 +1,553 @@ -import {HederaDid} from "../../hedera-did"; -import {DidSyntax} from "../../did-syntax"; -import {FileId, PrivateKey, PublicKey, TopicId} from "@hashgraph/sdk"; -import {Hashing} from "../../../utils/hashing"; -import {DidDocumentBase} from "../../did-document-base"; -import {HcsDidRootKey} from "./hcs-did-root-key"; - -/** - * Hedera Decentralized Identifier for Hedera DID Method specification based on HCS. - */ -export class HcsDid implements HederaDid { +import { + Client, + Hbar, + PrivateKey, + PublicKey, + Timestamp, + TopicCreateTransaction, + TopicId, + TopicUpdateTransaction, +} from "@hashgraph/sdk"; +import { Hashing } from "../../../utils/hashing"; +import { DidDocument } from "../../did-document"; +import { DidError, DidErrorCode } from "../../did-error"; +import { DidMethodOperation } from "../../did-method-operation"; +import { DidSyntax } from "../../did-syntax"; +import { MessageEnvelope } from "../message-envelope"; +import { HcsDidDeleteEvent } from "./event/document/hcs-did-delete-event"; +import { HcsDidEvent } from "./event/hcs-did-event"; +import { HcsDidCreateDidOwnerEvent } from "./event/owner/hcs-did-create-did-owner-event"; +import { HcsDidUpdateDidOwnerEvent } from "./event/owner/hcs-did-update-did-owner-event"; +import { HcsDidCreateServiceEvent } from "./event/service/hcs-did-create-service-event"; +import { HcsDidRevokeServiceEvent } from "./event/service/hcs-did-revoke-service-event"; +import { HcsDidUpdateServiceEvent } from "./event/service/hcs-did-update-service-event"; +import { ServiceTypes } from "./event/service/types"; +import { HcsDidCreateVerificationMethodEvent } from "./event/verification-method/hcs-did-create-verification-method-event"; +import { HcsDidRevokeVerificationMethodEvent } from "./event/verification-method/hcs-did-revoke-verification-method-event"; +import { HcsDidUpdateVerificationMethodEvent } from "./event/verification-method/hcs-did-update-verification-method-event"; +import { VerificationMethodSupportedKeyType } from "./event/verification-method/types"; +import { HcsDidCreateVerificationRelationshipEvent } from "./event/verification-relationship/hcs-did-create-verification-relationship-event"; +import { HcsDidRevokeVerificationRelationshipEvent } from "./event/verification-relationship/hcs-did-revoke-verification-relationship-event"; +import { HcsDidUpdateVerificationRelationshipEvent } from "./event/verification-relationship/hcs-did-update-verification-relationship-event"; +import { + VerificationRelationshipSupportedKeyType, + VerificationRelationshipType, +} from "./event/verification-relationship/types"; +import { HcsDidEventMessageResolver } from "./hcs-did-event-message-resolver"; +import { HcsDidMessage } from "./hcs-did-message"; +import { HcsDidTransaction } from "./hcs-did-transaction"; + +export class HcsDid { public static DID_METHOD = DidSyntax.Method.HEDERA_HCS; - private static DID_PARAMETER_VALUE_PARTS = 2; + public static TRANSACTION_FEE = new Hbar(2); + public static READ_TOPIC_MESSAGES_TIMEOUT = 5000; + + protected client: Client; + protected privateKey: PrivateKey; + protected identifier: string; + protected network: string; + protected topicId: TopicId; + + protected messages: HcsDidMessage[]; + protected resolvedAt: Timestamp; + protected document: DidDocument; + + protected onMessageConfirmed: (message: MessageEnvelope) => void; + + constructor(args: { + identifier?: string; + privateKey?: PrivateKey; + client?: Client; + onMessageConfirmed?: (message: MessageEnvelope) => void; + }) { + this.identifier = args.identifier; + this.privateKey = args.privateKey; + this.client = args.client; + this.onMessageConfirmed = args.onMessageConfirmed; + + if (!this.identifier && !this.privateKey) { + throw new DidError("identifier and privateKey cannot both be empty"); + } - private didTopicId: TopicId; - private addressBookFileId: FileId; - private network: string; - private idString: string; - private did: string; - private didRootKey: PublicKey; - private privateDidRootKey: PrivateKey; + if (this.identifier) { + const [networkName, topicId] = HcsDid.parseIdentifier(this.identifier); + this.network = networkName; + this.topicId = topicId; + } + } /** - * Creates a DID instance. - * - * @param network The Hedera DID network. - * @param didRootKey The public key from which DID is derived. - * @param addressBookFileId The appent's address book {@link FileId} - * @param didTopicId The appnet's DID topic ID. - */ - constructor(network: string, didRootKey: PublicKey, addressBookFileId: FileId, didTopicId?: TopicId); - /** - * Creates a DID instance with private DID root key. - * - * @param network The Hedera DID network. - * @param privateDidRootKey The private DID root key. - * @param addressBookFileId The appent's address book {@link FileId} - * @param didTopicId The appnet's DID topic ID. - */ - constructor(network: string, privateDidRootKey: PrivateKey, addressBookFileId: FileId, didTopicId?: TopicId); - /** - * Creates a DID instance without topic ID specification. - * - * @param network The Hedera DID network. - * @param didRootKey The public key from which DID is derived. - * @param addressBookFileId The appent's address book {@link FileId} + * Public API */ - constructor(network: string, didRootKey: PublicKey, addressBookFileId: FileId) - /** - * Creates a DID instance. - * - * @param network The Hedera DID network. - * @param idString The id-string of a DID. - * @param addressBookFileId The appent's address book {@link FileId} - * @param didTopicId The appnet's DID topic ID. - */ - constructor(network: string, idString: string, addressBookFileId: FileId, didTopicId?: TopicId); - constructor(...args: any[]) { - if ( - (typeof args[0] === 'string') && - (args[1] instanceof PublicKey) && - (args[2] instanceof FileId) && - ((args[4] instanceof TopicId) || args[4] === undefined) && - (args.length === 4) - ) { - const [network, didRootKey, addressBookFileId, didTopicId] = args; - this.didTopicId = didTopicId; - this.addressBookFileId = addressBookFileId; - this.network = network; - this.didRootKey = didRootKey; - this.idString = HcsDid.publicKeyToIdString(didRootKey); - this.did = this.buildDid(); - - return; + + public async register() { + this.validateClientConfig(); + + if (this.identifier) { + await this.resolve(); + + if (this.document.hasOwner()) { + throw new DidError("DID is already registered"); + } + } else { + /** + * Create topic + */ + const topicCreateTransaction = new TopicCreateTransaction() + .setMaxTransactionFee(HcsDid.TRANSACTION_FEE) + .setAdminKey(this.privateKey.publicKey) + .setSubmitKey(this.privateKey.publicKey) + .freezeWith(this.client); + + const sigTx = await topicCreateTransaction.sign(this.privateKey); + const txId = await sigTx.execute(this.client); + const topicId = (await txId.getReceipt(this.client)).topicId; + + this.topicId = topicId; + this.network = this.client.ledgerId.toString(); + this.identifier = this.buildIdentifier(this.privateKey.publicKey); + } + + /** + * Set ownership + */ + const event = new HcsDidCreateDidOwnerEvent( + this.identifier + "#did-root-key", + this.identifier, + this.privateKey.publicKey + ); + await this.submitTransaction(DidMethodOperation.CREATE, event, this.privateKey); + + return this; + } + + public async changeOwner(args: { controller: string; newPrivateKey: PrivateKey }) { + if (!this.identifier) { + throw new DidError("DID is not registered"); } - if ( - (typeof args[0] === 'string') && - (args[1] instanceof PrivateKey) && - (args[2] instanceof FileId) && - ((args[4] instanceof TopicId) || args[4] === undefined) && - (args.length === 4) - ) { - const [network, privateDidRootKey, addressBookFileId, didTopicId] = args - - this.didTopicId = didTopicId; - this.addressBookFileId = addressBookFileId; - this.network = network; - this.didRootKey = privateDidRootKey.publicKey; - this.idString = HcsDid.publicKeyToIdString(privateDidRootKey.publicKey); - this.did = this.buildDid(); - this.privateDidRootKey = privateDidRootKey; - - return; + this.validateClientConfig(); + + if (!args.newPrivateKey) { + throw new DidError("newPrivateKey is missing"); + } + + await this.resolve(); + + if (!this.document.hasOwner()) { + throw new DidError("DID is not registered or was recently deleted. DID has to be registered first."); } - if ( - (typeof args[0] === 'string') && - (args[1] instanceof PublicKey) && - (args[2] instanceof FileId) && - (args.length === 3) - ) { - const [network, didRootKey, addressBookFileId] = args; - - this.didTopicId = null; - this.addressBookFileId = addressBookFileId; - this.network = network; - this.didRootKey = didRootKey; - this.idString = HcsDid.publicKeyToIdString(didRootKey); - this.did = this.buildDid(); - - return; + /** + * Change owner of the topic + */ + const transaction = await new TopicUpdateTransaction() + .setTopicId(this.topicId) + .setAdminKey(args.newPrivateKey.publicKey) + .setSubmitKey(args.newPrivateKey.publicKey) + .freezeWith(this.client); + + const signTx = await (await transaction.sign(this.privateKey)).sign(args.newPrivateKey); + const txResponse = await signTx.execute(this.client); + await txResponse.getReceipt(this.client); + + this.privateKey = args.newPrivateKey; + + /** + * Send ownership change message to the topic + */ + await this.submitTransaction( + DidMethodOperation.UPDATE, + new HcsDidUpdateDidOwnerEvent( + this.getIdentifier() + "#did-root-key", + args.controller, + args.newPrivateKey.publicKey + ), + this.privateKey + ); + return this; + } + + public async delete() { + if (!this.identifier) { + throw new DidError("DID is not registered"); } - if ( - (typeof args[0] === 'string') && - (typeof args[1] === 'string') && - (args[2] instanceof FileId) && - ((args[4] instanceof TopicId) || args[4] === undefined) && - (args.length === 4) - ) { - const [network, idString, addressBookFileId, didTopicId] = args; + this.validateClientConfig(); - this.didTopicId = didTopicId; - this.addressBookFileId = addressBookFileId; - this.network = network; + await this.submitTransaction(DidMethodOperation.DELETE, new HcsDidDeleteEvent(), this.privateKey); + return this; + } - this.idString = idString; - this.did = this.buildDid(); + public async resolve(): Promise { + if (!this.identifier) { + throw new DidError("DID is not registered"); + } - return; + if (!this.client) { + throw new DidError("Client configuration is missing"); } - throw new Error('Couldn\'t find constructor'); + return new Promise((resolve, reject) => { + new HcsDidEventMessageResolver(this.topicId) + .setTimeout(HcsDid.READ_TOPIC_MESSAGES_TIMEOUT) + .whenFinished(async (messages) => { + this.messages = messages.map((msg) => msg.open()); + this.document = new DidDocument(this.identifier); + try { + await this.document.processMessages(this.messages); + resolve(this.document); + } catch (err) { + reject(err); + } + }) + .onError((err) => { + // console.error(err); + reject(err); + }) + .execute(this.client); + }); } /** - * Converts a Hedera DID string into {@link HcsDid} object. - * - * @param didString A Hedera DID string. - * @return {@link HcsDid} object derived from the given Hedera DID string. + * Meta-information about DID */ - public static fromString(didString: string): HcsDid { - if (!didString) { - throw new Error("DID string cannot be null"); - } - const mainParts = didString.split(DidSyntax.DID_PARAMETER_SEPARATOR); + /** + * Add a Service meta-information to DID + * @param args + * @returns this + */ + public async addService(args: { id: string; type: ServiceTypes; serviceEndpoint: string }) { + this.validateClientConfig(); + + const event = new HcsDidCreateServiceEvent(args.id, args.type, args.serviceEndpoint); + await this.submitTransaction(DidMethodOperation.CREATE, event, this.privateKey); - let - topicId: TopicId, - addressBookFileId: FileId; + return this; + } - const didParts = mainParts.shift().split(DidSyntax.DID_METHOD_SEPARATOR); + /** + * Update a Service meta-information to DID + * @param args + * @returns this + */ + public async updateService(args: { id: string; type: ServiceTypes; serviceEndpoint: string }) { + this.validateClientConfig(); - if (didParts.shift() !== DidSyntax.DID_PREFIX) { - throw new Error('DID string is invalid: invalid prefix.'); - } + const event = new HcsDidUpdateServiceEvent(args.id, args.type, args.serviceEndpoint); + await this.submitTransaction(DidMethodOperation.UPDATE, event, this.privateKey); - const methodName = didParts.shift(); - if (DidSyntax.Method.HEDERA_HCS !== methodName) { - throw new Error('DID string is invalid: invalid method name: ' + methodName); - } + return this; + } - try { - const networkName = didParts.shift(); + /** + * Revoke a Service meta-information to DID + * @param args + * @returns this + */ + public async revokeService(args: { id: string }) { + this.validateClientConfig(); - const params = this.extractParameters(mainParts, methodName, networkName); - addressBookFileId = FileId.fromString(params.get(DidSyntax.MethodSpecificParameter.ADDRESS_BOOK_FILE_ID)); - if (params.has(DidSyntax.MethodSpecificParameter.DID_TOPIC_ID)) { - topicId = TopicId.fromString(params.get(DidSyntax.MethodSpecificParameter.DID_TOPIC_ID)); - } - const didIdString = didParts.shift(); - if (didIdString.length < 32 || didParts.shift()) { - throw new Error('DID string is invalid.') - } + const event = new HcsDidRevokeServiceEvent(args.id); + await this.submitTransaction(DidMethodOperation.REVOKE, event, this.privateKey); - return new HcsDid(networkName, didIdString, addressBookFileId, topicId); + return this; + } - } catch (e) { - throw new Error('DID string is invalid. ' + e.message); - } + /** + * Add a Verification Method meta-information to DID + * @param args + * @returns this + */ + public async addVerificationMethod(args: { + id: string; + type: VerificationMethodSupportedKeyType; + controller: string; + publicKey: PublicKey; + }) { + this.validateClientConfig(); + + const event = new HcsDidCreateVerificationMethodEvent(args.id, args.type, args.controller, args.publicKey); + await this.submitTransaction(DidMethodOperation.CREATE, event, this.privateKey); + + return this; } /** - * Extracts method-specific URL parameters. - * - * @param mainParts Iterator over main parts of the DID. - * @param methodName The method name. - * @param networkName The network name. - * @return A map of method-specific URL parameters and their values. + * Update a Verification Method meta-information to DID + * @param args + * @returns this */ - private static extractParameters(mainParts: string[], methodName: string, networkName: string): Map { - const result = new Map(); - - const fidParamName = [methodName, networkName, DidSyntax.MethodSpecificParameter.ADDRESS_BOOK_FILE_ID].join(DidSyntax.DID_METHOD_SEPARATOR); - const tidParamName = [methodName, networkName, DidSyntax.MethodSpecificParameter.DID_TOPIC_ID].join(DidSyntax.DID_METHOD_SEPARATOR); - - let mp; - while(mp = mainParts.shift()) { - const paramValue = mp.split(DidSyntax.DID_PARAMETER_VALUE_SEPARATOR); - - if (paramValue.length != this.DID_PARAMETER_VALUE_PARTS) { - continue; - } else if (fidParamName === paramValue[0]) { - result.set(DidSyntax.MethodSpecificParameter.ADDRESS_BOOK_FILE_ID, paramValue[1]); - } else if (tidParamName === paramValue[0]) { - result.set(DidSyntax.MethodSpecificParameter.DID_TOPIC_ID, paramValue[1]); - } - } + public async updateVerificationMethod(args: { + id: string; + type: VerificationMethodSupportedKeyType; + controller: string; + publicKey: PublicKey; + }) { + this.validateClientConfig(); + + const event = new HcsDidUpdateVerificationMethodEvent(args.id, args.type, args.controller, args.publicKey); + await this.submitTransaction(DidMethodOperation.UPDATE, event, this.privateKey); + + return this; + } - if (!result.has(DidSyntax.MethodSpecificParameter.ADDRESS_BOOK_FILE_ID)) { - throw new Error('DID string is invalid. Required method-specific URL parameter not found: ' + DidSyntax.MethodSpecificParameter.ADDRESS_BOOK_FILE_ID); - } + /** + * Revoke a Verification Method meta-information to DID + * @param args + * @returns this + */ + public async revokeVerificationMethod(args: { id: string }) { + this.validateClientConfig(); - return result; + const event = new HcsDidRevokeVerificationMethodEvent(args.id); + await this.submitTransaction(DidMethodOperation.REVOKE, event, this.privateKey); + + return this; } /** - * Generates a random DID root key. - * - * @return A private key of generated public DID root key. + * Add a Verification Relationship to DID + * @param args + * @returns this */ - public static generateDidRootKey(): PrivateKey { - return PrivateKey.generate(); + public async addVerificationRelationship(args: { + id: string; + relationshipType: VerificationRelationshipType; + type: VerificationRelationshipSupportedKeyType; + controller: string; + publicKey: PublicKey; + }) { + this.validateClientConfig(); + + const event = new HcsDidCreateVerificationRelationshipEvent( + args.id, + args.relationshipType, + args.type, + args.controller, + args.publicKey + ); + await this.submitTransaction(DidMethodOperation.CREATE, event, this.privateKey); + + return this; } /** - * Generates DID document base from the given DID and its root key. - * - * @param didRootKey Public key used to build this DID. - * @return The DID document base. - * @throws IllegalArgumentException In case given DID root key does not match this DID. + * Update a Verification Relationship to DID + * @param args + * @returns this */ - public generateDidDocument(): DidDocumentBase { - const result = new DidDocumentBase(this.toDid()); - if (this.didRootKey) { - const rootKey = HcsDidRootKey.fromHcsIdentity(this, this.didRootKey); - result.setDidRootKey(rootKey); - } + public async updateVerificationRelationship(args: { + id: string; + relationshipType: VerificationRelationshipType; + type: VerificationRelationshipSupportedKeyType; + controller: string; + publicKey: PublicKey; + }) { + this.validateClientConfig(); + + const event = new HcsDidUpdateVerificationRelationshipEvent( + args.id, + args.relationshipType, + args.type, + args.controller, + args.publicKey + ); + await this.submitTransaction(DidMethodOperation.UPDATE, event, this.privateKey); + + return this; + } + + /** + * Revoke a Verification Relationship to DID + * @param args + * @returns this + */ + public async revokeVerificationRelationship(args: { id: string; relationshipType: VerificationRelationshipType }) { + this.validateClientConfig(); + + const event = new HcsDidRevokeVerificationRelationshipEvent(args.id, args.relationshipType); + await this.submitTransaction(DidMethodOperation.REVOKE, event, this.privateKey); - return result; + return this; } + /** + * Attribute getters + */ - public getNetwork(): string { - return this.network; + public getIdentifier() { + return this.identifier; + } + + public getClient() { + return this.client; + } + + public getPrivateKey() { + return this.privateKey; } - public getMethod(): DidSyntax.Method { - return DidSyntax.Method.HEDERA_HCS; + public getTopicId() { + return this.topicId; } - public toString(): string { - return this.did; + public getNetwork() { + return this.network; } - public getDidTopicId(): TopicId { - return this.didTopicId; + public getMethod() { + return HcsDid.DID_METHOD; } - public getAddressBookFileId(): FileId { - return this.addressBookFileId; + public getMessages() { + return this.messages; } - public getIdString(): string { - return this.idString; + /** + * Static methods + */ + + public static publicKeyToIdString(publicKey: PublicKey): string { + return Hashing.multibase.encode(publicKey.toBytes()); } - public toDid() { - return this.did + public static stringToPublicKey(idString: string): PublicKey { + return PublicKey.fromBytes(Hashing.multibase.decode(idString)); + } + + public static parsePublicKeyFromIdentifier(identifier: string): PublicKey { + const [_networkName, _topicId, didIdString] = HcsDid.parseIdentifier(identifier); + return HcsDid.stringToPublicKey(didIdString); } /** - * Constructs DID string from the instance of DID object. - * - * @return A DID string. + * Private */ - private buildDid(): string { + + private buildIdentifier(publicKey: PublicKey): string { const methodNetwork = [this.getMethod().toString(), this.network].join(DidSyntax.DID_METHOD_SEPARATOR); let ret: string; - ret = DidSyntax.DID_PREFIX + + ret = + DidSyntax.DID_PREFIX + DidSyntax.DID_METHOD_SEPARATOR + methodNetwork + DidSyntax.DID_METHOD_SEPARATOR + - this.idString + - DidSyntax.DID_PARAMETER_SEPARATOR + - methodNetwork + - DidSyntax.DID_METHOD_SEPARATOR + - DidSyntax.MethodSpecificParameter.ADDRESS_BOOK_FILE_ID + - DidSyntax.DID_PARAMETER_VALUE_SEPARATOR + - this.addressBookFileId.toString(); - - if(this.didTopicId) { - ret = ret + - DidSyntax.DID_PARAMETER_SEPARATOR + - methodNetwork + - DidSyntax.DID_METHOD_SEPARATOR + - DidSyntax.MethodSpecificParameter.DID_TOPIC_ID + - DidSyntax.DID_PARAMETER_VALUE_SEPARATOR + - this.didTopicId.toString(); - } + HcsDid.publicKeyToIdString(publicKey) + + DidSyntax.DID_TOPIC_SEPARATOR + + this.topicId.toString(); return ret; } - /** - * Constructs an id-string of a DID from a given public key. - * - * @param didRootKey Public Key from which the DID is created. - * @return The id-string of a DID that is a Base58-encoded SHA-256 hash of a given public key. - */ - public static publicKeyToIdString(didRootKey: PublicKey): string { - return Hashing.base58.encode(Hashing.sha256.digest(didRootKey.toBytes())); + public static parseIdentifier(identifier: string): [string, TopicId, string] { + const [didPart, topicIdPart] = identifier.split(DidSyntax.DID_TOPIC_SEPARATOR); + + if (!topicIdPart) { + throw new DidError("DID string is invalid: topic ID is missing", DidErrorCode.INVALID_DID_STRING); + } + + const topicId = TopicId.fromString(topicIdPart); + + const didParts = didPart.split(DidSyntax.DID_METHOD_SEPARATOR); + + if (didParts.shift() !== DidSyntax.DID_PREFIX) { + throw new DidError("DID string is invalid: invalid prefix.", DidErrorCode.INVALID_DID_STRING); + } + + const methodName = didParts.shift(); + if (DidSyntax.Method.HEDERA_HCS !== methodName) { + throw new DidError( + "DID string is invalid: invalid method name: " + methodName, + DidErrorCode.INVALID_DID_STRING + ); + } + + try { + const networkName = didParts.shift(); + + if ( + networkName != DidSyntax.HEDERA_NETWORK_MAINNET && + networkName != DidSyntax.HEDERA_NETWORK_TESTNET && + networkName != DidSyntax.HEDERA_NETWORK_PREVIEWNET + ) { + throw new DidError("DID string is invalid. Invalid Hedera network.", DidErrorCode.INVALID_NETWORK); + } + + const didIdString = didParts.shift(); + + if (didIdString.length < 44 || didParts.shift()) { + throw new DidError( + "DID string is invalid. ID holds incorrect format.", + DidErrorCode.INVALID_DID_STRING + ); + } + + return [networkName, topicId, didIdString]; + } catch (e) { + if (e instanceof DidError) { + throw e; + } + + throw new DidError("DID string is invalid. " + e.message, DidErrorCode.INVALID_DID_STRING); + } } - /** - * Returns a private key of DID root key. - * This is only available if it was provided during {@link HcsDid} construction. - * - * @return The private key of DID root key. - */ - public getPrivateDidRootKey(): PrivateKey { - return this.privateDidRootKey; + private validateClientConfig() { + if (!this.privateKey) { + throw new DidError("privateKey is missing"); + } + + if (!this.client) { + throw new DidError("Client configuration is missing"); + } } /** - * Returns a public key of DID root key. - * This is only available if it was provided during {@link HcsDid} construction. - * - * @return The private key of DID root key. + * Submit Message Transaction to Hashgraph + * @param didMethodOperation + * @param event + * @param privateKey + * @returns this */ - public getPublicDidRootKey(): PublicKey { - return this.didRootKey; + private async submitTransaction( + didMethodOperation: DidMethodOperation, + event: HcsDidEvent, + privateKey: PrivateKey + ): Promise> { + const message = new HcsDidMessage(didMethodOperation, this.getIdentifier(), event); + const envelope = new MessageEnvelope(message); + const transaction = new HcsDidTransaction(envelope, this.getTopicId()); + + return new Promise((resolve, reject) => { + transaction + .signMessage((msg) => { + return privateKey.sign(msg); + }) + .buildAndSignTransaction((tx) => { + return tx + .setMaxTransactionFee(HcsDid.TRANSACTION_FEE) + .freezeWith(this.client) + .sign(this.privateKey); + }) + .onError((err) => { + // console.error(err); + reject(err); + }) + .onMessageConfirmed((msg) => { + if (this.onMessageConfirmed) { + this.onMessageConfirmed(msg); + } + + console.log("Message Published"); + console.log( + `Explore on DragonGlass: https://testnet.dragonglass.me/hedera/topics/${this.getTopicId()}` + ); + resolve(msg); + }) + .execute(this.client); + }); } } diff --git a/src/identity/hcs/hcs-identity-network-builder.ts b/src/identity/hcs/hcs-identity-network-builder.ts deleted file mode 100644 index c616978..0000000 --- a/src/identity/hcs/hcs-identity-network-builder.ts +++ /dev/null @@ -1,103 +0,0 @@ -import {Client, FileCreateTransaction, Hbar, PublicKey, TopicCreateTransaction, TopicId} from "@hashgraph/sdk"; -import {HcsIdentityNetwork} from "./hcs-identity-network"; -import {AddressBook} from "./address-book"; - -export class HcsIdentityNetworkBuilder { - private appnetName: string; - private didTopicId: TopicId; - private vcTopicId: TopicId; - private network: string; - private didServers: string[]; - private publicKey: PublicKey; - private maxTransactionFee: Hbar = new Hbar(2); - private didTopicMemo: string = ''; - private vcTopicMemo: string = ''; - - public async execute(client: Client): Promise { - const didTopicCreateTransaction = new TopicCreateTransaction() - .setMaxTransactionFee(this.maxTransactionFee) - .setTopicMemo(this.didTopicMemo); - - if (this.publicKey) { - didTopicCreateTransaction.setAdminKey(this.publicKey); - } - - const didTxId = await didTopicCreateTransaction.execute(client); - this.didTopicId = (await didTxId.getReceipt(client)).topicId; - - const vcTopicCreateTransaction = new TopicCreateTransaction() - .setMaxTransactionFee(this.maxTransactionFee) - .setTopicMemo(this.vcTopicMemo); - - if (this.publicKey) { - vcTopicCreateTransaction.setAdminKey(this.publicKey); - } - - const vcTxId = await vcTopicCreateTransaction.execute(client); - this.vcTopicId = (await vcTxId.getReceipt(client)).topicId; - - const addressBook = AddressBook.create(this.appnetName, this.didTopicId.toString(), this.vcTopicId.toString(), this.didServers); - - const fileCreateTx = new FileCreateTransaction().setContents(addressBook.toJSON()); - - const response = await fileCreateTx.execute(client); - const receipt = await response.getReceipt(client); - const fileId = receipt.fileId; - - addressBook.setFileId(fileId); - - return HcsIdentityNetwork.fromAddressBook(this.network, addressBook); - } - - public addAppnetDidServer(serverUrl: string): HcsIdentityNetworkBuilder { - if (!this.didServers) { - this.didServers = []; - } - - if (this.didServers.indexOf(serverUrl) == -1) { - this.didServers.push(serverUrl); - } - - return this; - } - - public setAppnetName(appnetName: string): HcsIdentityNetworkBuilder { - this.appnetName = appnetName; - return this; - } - - public setDidTopicMemo(didTopicMemo: string): HcsIdentityNetworkBuilder { - this.didTopicMemo = didTopicMemo; - return this; - } - - public setVCTopicMemo(vcTopicMemo: string): HcsIdentityNetworkBuilder { - this.vcTopicMemo = vcTopicMemo; - return this; - } - - public setDidTopicId(didTopicId: TopicId): HcsIdentityNetworkBuilder { - this.didTopicId = didTopicId; - return this; - } - - public setVCTopicId(vcTopicId: TopicId): HcsIdentityNetworkBuilder { - this.vcTopicId = vcTopicId; - return this; - } - - public setMaxTransactionFee(maxTransactionFee: Hbar): HcsIdentityNetworkBuilder { - this.maxTransactionFee = maxTransactionFee; - return this; - } - - public setPublicKey(publicKey: PublicKey): HcsIdentityNetworkBuilder { - this.publicKey = publicKey; - return this; - } - - public setNetwork(network: string): HcsIdentityNetworkBuilder { - this.network = network; - return this; - } -} diff --git a/src/identity/hcs/hcs-identity-network.ts b/src/identity/hcs/hcs-identity-network.ts deleted file mode 100644 index 2b675b8..0000000 --- a/src/identity/hcs/hcs-identity-network.ts +++ /dev/null @@ -1,311 +0,0 @@ -import {AddressBook} from "./address-book"; -import {Client, FileContentsQuery, FileId, PrivateKey, PublicKey, TopicId} from "@hashgraph/sdk"; -import {HcsDid} from "./did/hcs-did"; -import {DidMethodOperation} from "../did-method-operation"; -import {HcsDidTransaction} from "./did/hcs-did-transaction"; -import {MessageEnvelope} from "./message-envelope"; -import {HcsVcMessage} from "./vc/hcs-vc-message"; -import {HcsDidMessage} from "./did/hcs-did-message"; -import {HcsVcTransaction} from "./vc/hcs-vc-transaction"; -import {HcsVcOperation} from "./vc/hcs-vc-operation"; -import {HcsDidResolver} from "./did/hcs-did-resolver"; -import {HcsDidTopicListener} from "./did/hcs-did-topic-listener"; -import {HcsVcStatusResolver} from "./vc/hcs-vc-status-resolver"; -import {HcsVcTopicListener} from "./vc/hcs-vc-topic-listener"; - -/** - * Appnet's identity network based on Hedera HCS DID method specification. - */ -export class HcsIdentityNetwork { - /** - * The address book of appnet's identity network. - */ - private addressBook: AddressBook; - - /** - * The Hedera network on which this identity network is created. - */ - private network: string; - - /** - * Instantiates existing identity network from a provided address book. - * - * @param network The Hedera network. - * @param addressBook The {@link AddressBook} of the identity network. - * @return The identity network instance. - */ - public static fromAddressBook(network: string, addressBook: AddressBook): HcsIdentityNetwork { - const result = new HcsIdentityNetwork(); - result.network = network; - result.addressBook = addressBook; - - return result; - } - - /** - * Instantiates existing identity network using an address book file read from Hedera File Service. - * - * @param client The Hedera network client. - * @param network The Hedera network. - * @param addressBookFileId The FileID of {@link AddressBook} file stored on Hedera File Service. - * @return The identity network instance. - */ - public static async fromAddressBookFile(client: Client, network: string, addressBookFileId: FileId): Promise { - const fileContentsQueryCost = (new FileContentsQuery()).setFileId(addressBookFileId).getCost(client); - const fileQuery = (new FileContentsQuery()).setFileId(addressBookFileId); - - const contents = await fileQuery.execute(client); - - const result = new HcsIdentityNetwork(); - result.network = network; - result.addressBook = AddressBook.fromJson(contents.toString(), addressBookFileId); - - return result; - } - - /** - * Instantiates existing identity network using a DID generated for this network. - * - * @param client The Hedera network client. - * @param hcsDid The Hedera HCS DID. - * @return The identity network instance. - */ - public static async fromHcsDid(client: Client, hcsDid: HcsDid): Promise { - const addressBookFileId = hcsDid.getAddressBookFileId(); - return await HcsIdentityNetwork.fromAddressBookFile(client, hcsDid.getNetwork(), addressBookFileId); - } - - /** - * Instantiates a {@link HcsDidTransaction} to perform the specified operation on the DID document. - * - * @param operation The operation to be performed on a DID document. - * @return The {@link HcsDidTransaction} instance. - */ - public createDidTransaction(operation: DidMethodOperation): HcsDidTransaction; - - /** - * Instantiates a {@link HcsDidTransaction} to perform the specified operation on the DID document. - * - * @param message The DID topic message ready to for sending. - * @return The {@link HcsDidTransaction} instance. - */ - public createDidTransaction(message: MessageEnvelope): HcsDidTransaction; - - public createDidTransaction(...args): HcsDidTransaction { - if ( - (args.length === 1) && - (args[0] instanceof MessageEnvelope) - ) { - const [message] = args; - return new HcsDidTransaction(message, this.getDidTopicId()); - } else if ( - (args.length === 1) - // (args[0] instanceof DidMethodOperation) - ) { - const [operation] = args; - return new HcsDidTransaction(operation, this.getDidTopicId()); - } else { - throw new Error('Invalid arguments'); - } - } - - /** - * Instantiates a {@link HcsVcTransaction} to perform the specified operation on the VC document. - * - * @param operation The type of operation. - * @param credentialHash Credential hash. - * @param signerPublicKey Public key of the signer (issuer). - * @return The transaction instance. - */ - public createVcTransaction(operation: HcsVcOperation, credentialHash: string, signerPublicKey: PublicKey): HcsVcTransaction; - - /** - * Instantiates a {@link HcsVcTransaction} to perform the specified operation on the VC document status. - * - * @param message The VC topic message ready to for sending. - * @param signerPublicKey Public key of the signer (usually issuer). - * @return The {@link HcsVcTransaction} instance. - */ - public createVcTransaction(message: MessageEnvelope, signerPublicKey: PublicKey): HcsVcTransaction; - - public createVcTransaction(...args): HcsVcTransaction { - if ( - (args.length === 3) && - // (args[0] instanceof HcsVcOperation) && - (typeof args[1] === 'string') && - (args[2] instanceof PublicKey) - ) { - const [operation, credentialHash, signerPublicKey] = args; - return new HcsVcTransaction(this.getVcTopicId(), operation, credentialHash, signerPublicKey); - } else if ( - (args.length === 2) && - (args[0] instanceof MessageEnvelope) && - (args[1] instanceof PublicKey) - ) { - const [message, signerPublicKey] = args; - return new HcsVcTransaction(this.getVcTopicId(), message, signerPublicKey); - } else { - throw new Error('Invalid arguments'); - } - } - - /** - * Returns the Hedera network on which this identity network runs. - * - * @return The Hedera network. - */ - public getNetwork(): string { - return this.network; - } - - /** - * Generates a new DID and it's root key. - * - * @param withTid Indicates if DID topic ID should be added to the DID as tid parameter. - * @return Generated {@link HcsDid} with it's private DID root key. - */ - public generateDid(withTid: boolean): HcsDid; - - public generateDid(privateKey: PrivateKey, withTid: boolean): HcsDid; - - /** - * Generates a new DID from the given public DID root key. - * - * @param publicKey A DID root key. - * @param withTid Indicates if DID topic ID should be added to the DID as tid parameter. - * @return A newly generated DID. - */ - public generateDid(publicKey: PublicKey, withTid: boolean): HcsDid; - public generateDid(...args): HcsDid { - if ( - (args.length === 1) && - (typeof args[0] === 'boolean') - ) { - const [withTid] = args; - const privateKey = HcsDid.generateDidRootKey(); - const tid = withTid ? this.getDidTopicId() : null; - - return new HcsDid(this.getNetwork(), privateKey, this.addressBook.getFileId(), tid); - } else if ( - (args.length === 2) && - (args[0] instanceof PublicKey) && - (typeof args[1] === 'boolean') - ) { - const [publicKey, withTid] = args; - const tid = withTid ? this.getDidTopicId() : null; - - return new HcsDid(this.getNetwork(), publicKey, this.addressBook.getFileId(), tid); - } else if ( - (args.length === 2) && - (args[0] instanceof PrivateKey) && - (typeof args[1] === 'boolean') - ) { - const [privateKey, withTid] = args; - const tid = withTid ? this.getDidTopicId() : null; - - return new HcsDid(this.getNetwork(), privateKey, this.addressBook.getFileId(), tid); - } - } - - /** - * Returns a DID resolver for this network. - * - * @return The DID resolver for this network. - */ - public getDidResolver(): HcsDidResolver { - return new HcsDidResolver(this.getDidTopicId()); - } - - /** - * Returns DID topic ID for this network. - * - * @return The DID topic ID. - */ - public getDidTopicId(): TopicId { - return TopicId.fromString(this.addressBook.getDidTopicId()); - } - - /** - * Returns a DID topic listener for this network. - * - * @return The DID topic listener. - */ - public getDidTopicListener(): HcsDidTopicListener { - return new HcsDidTopicListener(this.getDidTopicId()); - } - - /** - * Returns Verifiable Credentials topic ID for this network. - * - * @return The VC topic ID. - */ - public getVcTopicId(): TopicId { - return TopicId.fromString(this.addressBook.getVcTopicId()); - } - - /** - * Returns the address book of this identity network. - * - * @return The address book of this identity network. - */ - public getAddressBook(): AddressBook { - return this.addressBook; - } - - /** - * Returns a VC status resolver for this network. - * - * @return The VC status resolver for this network. - */ - public getVcStatusResolver(): HcsVcStatusResolver; - - /** - * Returns a VC status resolver for this network. - * Resolver will validate signatures of topic messages against public keys supplied - * by the given provider. - * - * @param publicKeysProvider Provider of a public keys acceptable for a given VC hash. - * @return The VC status resolver for this network. - */ - public getVcStatusResolver(publicKeysProvider: (t: string) => PublicKey[]): HcsVcStatusResolver; - - public getVcStatusResolver(...args): HcsVcStatusResolver { - if (args.length === 0) { - return new HcsVcStatusResolver(this.getVcTopicId()); - } else if (args.length === 1) { - const [publicKeysProvider] = args; - return new HcsVcStatusResolver(this.getVcTopicId(), publicKeysProvider); - } else { - throw Error('Invalid arguments'); - } - } - - /** - * Returns a VC topic listener for this network. - * - * @return The VC topic listener. - */ - public getVcTopicListener(): HcsVcTopicListener; - - /** - * Returns a VC topic listener for this network. - * This listener will validate signatures of topic messages against public keys supplied - * by the given provider. - * - * @param publicKeysProvider Provider of a public keys acceptable for a given VC hash. - * @return The VC topic listener. - */ - public getVcTopicListener(publicKeysProvider: (t: string) => PublicKey[]): HcsVcTopicListener; - - public getVcTopicListener(...args): HcsVcTopicListener { - if (args.length === 0) { - return new HcsVcTopicListener(this.getVcTopicId()); - } else if (args.length === 1) { - const [publicKeysProvider] = args; - return new HcsVcTopicListener(this.getVcTopicId(), publicKeysProvider); - } else { - throw new Error('Invalid arguments'); - } - } - -} diff --git a/src/identity/hcs/json-class.ts b/src/identity/hcs/json-class.ts index c04917a..41739b5 100644 --- a/src/identity/hcs/json-class.ts +++ b/src/identity/hcs/json-class.ts @@ -1,3 +1,3 @@ export type JsonClass = { fromJsonTree(json: any, result?: U): U; -} \ No newline at end of file +}; diff --git a/src/identity/hcs/message-envelope.ts b/src/identity/hcs/message-envelope.ts index 3cafc89..1a32c27 100644 --- a/src/identity/hcs/message-envelope.ts +++ b/src/identity/hcs/message-envelope.ts @@ -1,25 +1,24 @@ -import { Decrypter, Encrypter, Message } from "./message"; -import Long from "long"; -import { MessageMode } from "./message-mode"; -import { SerializableMirrorConsensusResponse } from "./serializable-mirror-consensus-response"; import { PublicKey, Timestamp, TopicMessage } from "@hashgraph/sdk"; -import { JsonClass } from "./json-class"; import { Base64 } from "js-base64"; +import Long from "long"; +import { HcsDidMessage } from "../.."; import { ArraysUtils } from "../../utils/arrays-utils"; +import { DidError } from "../did-error"; +import { JsonClass } from "./json-class"; +import { SerializableMirrorConsensusResponse } from "./serializable-mirror-consensus-response"; -export type PublicKeyProvider = (evn: MessageEnvelope) => PublicKey; +export type PublicKeyProvider = (evn: MessageEnvelope) => PublicKey; export type SignFunction = (message: Uint8Array) => Uint8Array; /** * The envelope for Hedera identity messages sent to HCS DID or VC topics. */ -export class MessageEnvelope { - private static MESSAGE_KEY = 'message'; - private static SIGNATURE_KEY = 'signature'; +export class MessageEnvelope { + private static MESSAGE_KEY = "message"; + private static SIGNATURE_KEY = "signature"; private static serialVersionUID = Long.fromInt(1); - protected mode: MessageMode; protected message: T; protected signature: string; @@ -28,8 +27,7 @@ export class MessageEnvelope { return null; } return this.message.toJSON(); - }; - protected decryptedMessage: T; + } protected mirrorResponse: SerializableMirrorConsensusResponse; /** @@ -42,18 +40,15 @@ export class MessageEnvelope { constructor(...args: any[]) { if (args.length === 0) { // do nothing - } - else if (args.length === 1) { + } else if (args.length === 1) { const [message] = args; this.message = message; - this.mode = MessageMode.PLAIN; } else { - throw new Error('Wrong arguments passed to constructor'); + throw new DidError("Wrong arguments passed to constructor"); } } - /** * Signs this message envelope with the given signing function. * @@ -62,11 +57,11 @@ export class MessageEnvelope { */ public sign(signer: SignFunction): Uint8Array { if (!signer) { - throw new Error('Signing function is not provided.'); + throw new DidError("Signing function is not provided."); } if (this.signature) { - throw new Error('Message is already signed.'); + throw new DidError("Message is already signed."); } const msgBytes = ArraysUtils.fromString(this.message.toJSON()); @@ -78,7 +73,6 @@ export class MessageEnvelope { public toJsonTree(): any { const result: any = {}; - result.mode = this.mode; if (this.message) { result[MessageEnvelope.MESSAGE_KEY] = this.message.toJsonTree(); } @@ -105,15 +99,18 @@ export class MessageEnvelope { * @param messageClass Class type of the message inside envelope. * @return The {@link MessageEnvelope}. */ - public static fromMirrorResponse(response: TopicMessage, messageClass: JsonClass): MessageEnvelope { + public static fromMirrorResponse( + response: TopicMessage, + messageClass: JsonClass + ): MessageEnvelope { const msgJson = ArraysUtils.toString(response.contents); const result = MessageEnvelope.fromJson(msgJson, messageClass); + // console.log(result); result.mirrorResponse = new SerializableMirrorConsensusResponse(response); return result; } - /** * Converts a VC topic message from a JSON string into object instance. * @@ -122,36 +119,24 @@ export class MessageEnvelope { * @param messageClass Class of the message inside envelope. * @return The {@link MessageEnvelope}. */ - public static fromJson(json: string, messageClass: JsonClass): MessageEnvelope { + public static fromJson(json: string, messageClass: JsonClass): MessageEnvelope { const result = new MessageEnvelope(); - const root = JSON.parse(json) - result.mode = root.mode; - result.signature = root[MessageEnvelope.SIGNATURE_KEY]; - if (root.hasOwnProperty(MessageEnvelope.MESSAGE_KEY)) { - result.message = messageClass.fromJsonTree(root[MessageEnvelope.MESSAGE_KEY]); - } else { + let root; + try { + root = JSON.parse(json); + result.signature = root[MessageEnvelope.SIGNATURE_KEY]; + if (root.hasOwnProperty(MessageEnvelope.MESSAGE_KEY)) { + result.message = messageClass.fromJsonTree(root[MessageEnvelope.MESSAGE_KEY]); + } else { + result.message = null; + } + } catch (err) { + console.warn(`Invalid message JSON message - it will be ignored`); + // Invalid json - ignore the message result.message = null; } - return result; - } - - - /** - * Encrypts the message in this envelope and returns its encrypted instance. - * - * @param encrypter The function used to encrypt the message. - * @return This envelope instance. - */ - public encrypt(encrypter: Encrypter): MessageEnvelope { - if (!encrypter) { - throw new Error('The encryption function is not provided.'); - } - - this.decryptedMessage = this.message; - this.message = encrypter(this.message); - this.mode = MessageMode.ENCRYPTED; - return this; + return result; } /** @@ -185,7 +170,6 @@ export class MessageEnvelope { return publicKey.verify(messageBytes, signatureToVerify); } - /** * Opens a message in this envelope. * If the message is encrypted, the given decrypter will be used first to decrypt it. @@ -194,20 +178,8 @@ export class MessageEnvelope { * @param decrypter The function used to decrypt the message. * @return The message object in a plain mode. */ - public open(decrypter: Decrypter = null): T { - if (this.decryptedMessage != null) { - return this.decryptedMessage; - } - - if (MessageMode.ENCRYPTED !== this.mode) { - this.decryptedMessage = this.message; - } else if (!decrypter) { - throw new Error("The message is encrypted, provide decryption function."); - } else if (!this.decryptedMessage) { - this.decryptedMessage = decrypter(this.message, this.getConsensusTimestamp()); - } - - return this.decryptedMessage; + public open(): T { + return this.message; } public getSignature(): string { @@ -215,11 +187,7 @@ export class MessageEnvelope { } public getConsensusTimestamp(): Timestamp { - return (!this.mirrorResponse) ? null : this.mirrorResponse.consensusTimestamp; - } - - public getMode(): MessageMode { - return this.mode; + return !this.mirrorResponse ? null : this.mirrorResponse.consensusTimestamp; } public getMirrorResponse(): SerializableMirrorConsensusResponse { diff --git a/src/identity/hcs/message-listener.ts b/src/identity/hcs/message-listener.ts deleted file mode 100644 index a9c691a..0000000 --- a/src/identity/hcs/message-listener.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { Decrypter, Message } from "./message"; -import { Client, Timestamp, TopicId, TopicMessage, TopicMessageQuery } from "@hashgraph/sdk"; -import SubscriptionHandle from "@hashgraph/sdk/lib/topic/SubscriptionHandle"; -import { MessageEnvelope } from "./message-envelope"; -import { MessageMode } from "./message-mode"; -import Long from "long"; - -/** - * A listener of confirmed messages from a HCS identity topic. - * Messages are received from a given mirror node, parsed and validated. - */ -export abstract class MessageListener { - protected topicId: TopicId; - protected query: TopicMessageQuery; - protected errorHandler: (input: Error) => void; - protected ignoreErrors: boolean; - protected decrypter: Decrypter; - protected subscriptionHandle: SubscriptionHandle; - protected filters: ((input: TopicMessage) => boolean)[]; - protected invalidMessageHandler: (t: TopicMessage, u: string) => void; - - /** - * Creates a new instance of a topic listener for the given consensus topic. - * By default, invalid messages are ignored and errors are not. - * - * @param topicId The consensus topic ID. - */ - constructor(topicId: TopicId) { - this.topicId = topicId; - this.query = new TopicMessageQuery().setTopicId(topicId); - this.ignoreErrors = false; - } - - /** - * Extracts and parses the message inside the response object into the given type. - * - * @param response Response message coming from the mirror node for for this listener's topic. - * @return The message inside an envelope. - */ - protected abstract extractMessage(response: TopicMessage): MessageEnvelope; - - /** - * Validates the message and its envelope signature. - * - * @param message The message inside an envelope. - * @param response Response message coming from the mirror node for for this listener's topic. - * @return True if the message is valid, False otherwise. - */ - protected abstract isMessageValid(message: MessageEnvelope, response: TopicMessage): boolean; - - /** - * Adds a custom filter for topic responses from a mirror node. - * Messages that do not pass the test are skipped before any other checks are run. - * - * @param filter The filter function. - * @return This listener instance. - */ - public addFilter(filter: (input: TopicMessage) => boolean): MessageListener { - if (!this.filters) { - this.filters = []; - } - this.filters.push(filter); - - return this; - } - - /** - * Subscribes to mirror node topic messages stream. - * - * @param client Mirror client instance. - * @param receiver Receiver of parsed messages. - * @return This listener instance. - */ - public subscribe(client: Client, receiver: (input: MessageEnvelope) => void): MessageListener { - const errorHandler = (message: TopicMessage, error: Error) => { - this.handleError(error); - }; - const listener = (message: TopicMessage) => { - this.handleResponse(message, receiver); - }; - - this.subscriptionHandle = this.query.subscribe(client, errorHandler, listener); - - return this; - } - - /** - * Stops receiving messages from the topic. - */ - public unsubscribe(): void { - if (this.subscriptionHandle) { - this.subscriptionHandle.unsubscribe(); - } - } - - /** - * Handles incoming messages from the topic on a mirror node. - * - * @param response Response message coming from the mirror node for the topic. - * @param receiver Consumer of the result message. - */ - protected handleResponse(response: TopicMessage, receiver: (input: MessageEnvelope) => void) { - if (this.filters) { - for (let filter of this.filters) { - if (!filter(response)) { - this.reportInvalidMessage(response, "Message was rejected by external filter"); - return; - } - } - } - - const envelope = this.extractMessage(response); - - if (!envelope) { - this.reportInvalidMessage(response, "Extracting envelope from the mirror response failed"); - return; - } - - if ((MessageMode.ENCRYPTED === envelope.getMode()) && !this.decrypter) { - this.reportInvalidMessage(response, "Message is encrypted and no decryption function was provided"); - return; - } - - if (this.isMessageValid(envelope, response)) { - receiver(envelope); - } - } - - /** - * Handles the given error internally. - * If external error handler is defined, passes the error there, otherwise raises RuntimeException or ignores it - * depending on a ignoreErrors flag. - * - * @param err The error. - * @throws RuntimeException Runtime exception with the given error in case external error handler is not defined - * and errors were not requested to be ignored. - */ - protected handleError(err: Error): void { - if (this.errorHandler) { - this.errorHandler(err); - } else if (!this.ignoreErrors) { - throw new Error(err.message); - } - } - - /** - * Reports invalid message to the handler. - * - * @param response The mirror response. - * @param reason The reason why message validation failed. - */ - protected reportInvalidMessage(response: TopicMessage, reason: string): void { - if (this.invalidMessageHandler) { - this.invalidMessageHandler(response, reason); - } - } - - /** - * Defines a handler for errors when they happen during execution. - * - * @param handler The error handler. - * @return This transaction instance. - */ - public onError(handler: (input: Error) => void): MessageListener { - this.errorHandler = handler; - return this; - } - - /** - * Defines a handler for invalid messages received from the topic. - * The first parameter of the handler is the mirror response. - * The second parameter is the reason why the message failed validation (if available). - * - * @param handler The invalid message handler. - * @return This transaction instance. - */ - public onInvalidMessageReceived(handler: (t: TopicMessage, u: string) => void): MessageListener { - this.invalidMessageHandler = handler; - return this; - } - - /** - * Defines decryption function that decrypts submitted message attributes after consensus is reached. - * Decryption function must accept a byte array of encrypted message and an Timestamp that is its consensus timestamp, - * If decrypter is not specified, encrypted messages will be ignored. - * - * @param decrypter The decryption function to use. - * @return This transaction instance. - */ - public onDecrypt(decrypter: Decrypter): MessageListener { - this.decrypter = decrypter; - return this; - } - - public setStartTime(startTime: Timestamp): MessageListener { - this.query.setStartTime(startTime); - return this; - } - - public setEndTime(endTime: Timestamp): MessageListener { - this.query.setEndTime(endTime); - return this; - } - - public setLimit(messagesLimit: Long): MessageListener { - this.query.setLimit(messagesLimit); - return this; - } - - public setIgnoreErrors(ignoreErrors: boolean): MessageListener { - this.ignoreErrors = ignoreErrors; - return this; - } -} diff --git a/src/identity/hcs/message-mode.ts b/src/identity/hcs/message-mode.ts deleted file mode 100644 index 41322db..0000000 --- a/src/identity/hcs/message-mode.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum MessageMode { - PLAIN = 'plain', - ENCRYPTED = 'encrypted' -} diff --git a/src/identity/hcs/message-resolver.ts b/src/identity/hcs/message-resolver.ts deleted file mode 100644 index 303eefd..0000000 --- a/src/identity/hcs/message-resolver.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Decrypter, Message } from "./message"; -import Long from "long"; -import { Client, Timestamp, TopicId } from "@hashgraph/sdk"; -import { MessageEnvelope } from "./message-envelope"; -import { MessageListener } from "./message-listener"; -import { Validator } from "../../utils/validator"; -import { TimestampUtils } from "../../utils/timestamp-utils"; -import { Sleep } from "../../utils/sleep"; - -export abstract class MessageResolver { - /** - * Default time to wait before finishing resolution and after the last message was received. - */ - public static DEFAULT_TIMEOUT: Long = Long.fromInt(30000); - - protected topicId: TopicId; - protected results: Map>; - - private lastMessageArrivalTime: Long; - private resultsHandler: (input: Map>) => void; - private errorHandler: (input: Error) => void; - private decrypter: Decrypter; - private existingSignatures: string[]; - private listener: MessageListener - private noMoreMessagesTimeout: Long; - - /** - * Instantiates a message resolver. - * - * @param topicId Consensus topic ID. - */ - constructor(topicId: TopicId) { - this.topicId = topicId; - this.results = new Map(); - this.noMoreMessagesTimeout = MessageResolver.DEFAULT_TIMEOUT; - this.lastMessageArrivalTime = Long.fromInt(Date.now()); - } - - /** - * Checks if the message matches preliminary search criteria. - * - * @param message The message read from the topic. - * @return True if the message matches search criteria, false otherwise. - */ - protected abstract matchesSearchCriteria(message: T): boolean; - - /** - * Applies custom filters on the message and if successfully verified, adds it to the results map. - * - * @param envelope Message inside an envelope in PLAIN mode. - */ - protected abstract processMessage(envelope: MessageEnvelope): void; - - /** - * Supplies message listener for messages of specified type. - * - * @return The {@link MessageListener} instance. - */ - protected abstract supplyMessageListener(): MessageListener; - - /** - * Resolves queries defined in implementing classes against a mirror node. - * - * @param client The mirror node client. - */ - public execute(client: Client): void { - new Validator().checkValidationErrors('Resolver not executed: ', v => { - return this.validate(v); - }); - - this.existingSignatures = []; - - this.listener = this.supplyMessageListener(); - - this.listener.setStartTime(new Timestamp(0, 0)) - .setEndTime(Timestamp.fromDate(new Date())) - .setIgnoreErrors(false) - .onError(this.errorHandler) - .onDecrypt(this.decrypter) - .subscribe(client, msg => { - return this.handleMessage(msg); - }); - - this.lastMessageArrivalTime = Long.fromInt(Date.now()); - this.waitOrFinish(); - } - - /** - * Handles incoming DID messages from DID Topic on a mirror node. - * - * @param envelope The parsed message envelope in a PLAIN mode. - */ - private handleMessage(envelope: MessageEnvelope): void { - this.lastMessageArrivalTime = Long.fromInt(Date.now()); - - if (!this.matchesSearchCriteria(envelope.open())) { - return; - } - - if (this.existingSignatures.indexOf(envelope.getSignature()) != -1) { - return; - } - - this.existingSignatures.push(envelope.getSignature()); - this.processMessage(envelope); - } - - /** - * Waits for a new message from the topic for the configured amount of time. - */ - protected async waitOrFinish(): Promise { - const timeDiff = Long.fromInt(Date.now()).sub(this.lastMessageArrivalTime); - - if (timeDiff.lt(this.noMoreMessagesTimeout)) { - await Sleep(this.noMoreMessagesTimeout.sub(timeDiff).toNumber()); - await this.waitOrFinish(); - return; - } - - this.resultsHandler(this.results); - - if (this.listener) { - this.listener.unsubscribe(); - } - } - - /** - * Defines a handler for resolution results. - * This will be called when the resolution process is finished. - * - * @param handler The results handler. - * @return This resolver instance. - */ - public whenFinished(handler: (input: Map>) => void): MessageResolver { - this.resultsHandler = handler; - return this; - } - - /** - * Defines a handler for errors when they happen during resolution. - * - * @param handler The error handler. - * @return This resolver instance. - */ - public onError(handler: (input: Error) => void): MessageResolver { - this.errorHandler = handler; - return this; - } - - /** - * Defines a maximum time in milliseconds to wait for new messages from the topic. - * Default is 30 seconds. - * - * @param timeout The timeout in milliseconds to wait for new messages from the topic. - * @return This resolver instance. - */ - public setTimeout(timeout: Long | number): MessageResolver { - this.noMoreMessagesTimeout = Long.fromValue(timeout); - return this; - } - - /** - * Defines decryption function that decrypts submitted the message after consensus was reached. - * Decryption function must accept a byte array of encrypted message and an Instant that is its consensus timestamp, - * If decrypter is not specified, encrypted messages will be ignored. - * - * @param decrypter The decrypter to use. - * @return This resolver instance. - */ - public onDecrypt(decrypter: Decrypter): MessageResolver { - this.decrypter = decrypter; - return this; - } - - /** - * Runs validation logic of the resolver's configuration. - * - * @param validator The errors validator. - */ - protected validate(validator: Validator): void { - validator.require(this.results.size > 0, 'Nothing to resolve.'); - validator.require(!!this.topicId, 'Consensus topic ID not defined.'); - validator.require(!!this.resultsHandler, 'Results handler \'whenFinished\' not defined.'); - } -} diff --git a/src/identity/hcs/message-transaction.ts b/src/identity/hcs/message-transaction.ts deleted file mode 100644 index 7ce5595..0000000 --- a/src/identity/hcs/message-transaction.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { Decrypter, Encrypter, Message, Signer } from "./message"; -import { Client, Timestamp, TopicId, TopicMessageSubmitTransaction, Transaction, TransactionId } from "@hashgraph/sdk"; -import { MessageEnvelope } from "./message-envelope"; -import { MessageListener } from "./message-listener"; -import { Validator } from "../../utils/validator"; -import moment from "moment"; -import { ArraysUtils } from "../../utils/arrays-utils"; - -export abstract class MessageTransaction { - private static SUBTRACT_TIME = 1; // seconds - - protected topicId: TopicId; - protected message: MessageEnvelope; - - private encrypter: Encrypter; - private decrypter: Decrypter; - private buildTransactionFunction: (input: TopicMessageSubmitTransaction) => Transaction; - private receiver: (input: MessageEnvelope) => void; - private errorHandler: (input: Error) => void; - private executed: boolean; - private signer: Signer; - private listener: MessageListener; - - /** - * Creates a new instance of a message transaction. - * - * @param topicId Consensus topic ID to which message will be submitted. - */ - constructor(topicId: TopicId); - /** - * Creates a new instance of a message transaction with already prepared message. - * - * @param topicId Consensus topic ID to which message will be submitted. - * @param message The message signed and ready to be sent. - */ - constructor(topicId: TopicId, message: MessageEnvelope); - constructor(...args) { - if (args.length === 1) { - const [topicId] = args; - this.topicId = topicId; - this.executed = false; - } else if (args.length === 2) { - const [topicId, message] = args; - this.topicId = topicId; - this.message = message; - this.executed = false; - } else { - throw new Error('Invalid arguments'); - } - } - - /** - * Method that constructs a message envelope with a message of type T. - * - * @return The message envelope with a message inside ready to sign. - */ - protected abstract buildMessage(): MessageEnvelope; - - /** - * Provides an instance of a message encrypter. - * - * @param encryptionFunction Encryption function used to encrypt single message property. - * @return The message encrypter instance. - */ - protected abstract provideMessageEncrypter(encryptionFunction: Encrypter): (input: T) => T; - - /** - * Provides a {@link MessageListener} instance specific to the submitted message type. - * - * @param topicIdToListen ID of the HCS topic. - * @return The topic listener for this message on a mirror node. - */ - protected abstract provideTopicListener(topicIdToListen: TopicId): MessageListener; - - /** - * Handles the error. - * If external error handler is defined, passes the error there, otherwise raises RuntimeException. - * - * @param err The error. - * @throws RuntimeException Runtime exception with the given error in case external error handler is not defined. - */ - protected handleError(err: Error): void { - if (this.errorHandler) { - this.errorHandler(err); - } else { - throw new Error(err.message); - } - } - - /** - * Defines encryption function that encrypts the message attributes before submission. - * - * @param encrypter The encrypter to use. - * @return This transaction instance. - */ - public onEncrypt(encrypter: Encrypter): MessageTransaction { - this.encrypter = encrypter; - return this; - } - - /** - * Handles event from a mirror node when a message was consensus was reached and message received. - * - * @param receiver The receiver handling incoming message. - * @return This transaction instance. - */ - public onMessageConfirmed(receiver: (input: MessageEnvelope) => void): MessageTransaction { - this.receiver = receiver; - return this; - } - - /** - * Defines a handler for errors when they happen during execution. - * - * @param handler The error handler. - * @return This transaction instance. - */ - public onError(handler: (input: Error) => void): MessageTransaction { - this.errorHandler = handler; - return this; - } - - /** - * Defines decryption function that decrypts message attributes after consensus is reached. - * Decryption function must accept a byte array of encrypted message and an Timestamp that is its consensus timestamp, - * - * @param decrypter The decrypter to use. - * @return This transaction instance. - */ - public onDecrypt(decrypter: Decrypter): MessageTransaction { - this.decrypter = decrypter; - return this; - } - - /** - * Defines a function that signs the message. - * - * @param signer The signing function to set. - * @return This transaction instance. - */ - public signMessage(signer: Signer): MessageTransaction { - this.signer = signer; - return this; - } - - /** - * Sets {@link TopicMessageSubmitTransaction} parameters, builds and signs it without executing it. - * Topic ID and transaction message content are already set in the incoming transaction. - * - * @param builderFunction The transaction builder function. - * @return This transaction instance. - */ - public buildAndSignTransaction(builderFunction: (input: TopicMessageSubmitTransaction) => Transaction): MessageTransaction { - this.buildTransactionFunction = builderFunction; - return this; - } - - /** - * Builds the message and submits it to appnet's topic. - * - * @param client The hedera network client. - * @return Transaction ID. - */ - public async execute(client: Client): Promise { - new Validator().checkValidationErrors('MessageTransaction execution failed: ', v => { - return this.validate(v); - }); - - const envelope = !this.message ? this.buildMessage() : this.message; - - if (this.encrypter) { - envelope.encrypt(this.provideMessageEncrypter(this.encrypter)); - } - - const messageContent = !envelope.getSignature() ? envelope.sign(this.signer) : ArraysUtils.fromString(envelope.toJSON()); - - if (this.receiver) { - this.listener = this.provideTopicListener(this.topicId); - this.listener.setStartTime(Timestamp.fromDate(moment().subtract(MessageTransaction.SUBTRACT_TIME, 'seconds').toDate())) - .setIgnoreErrors(false) - .addFilter((response) => { - return ArraysUtils.equals(messageContent, response.contents); - }) - .onError(err => { - return this.handleError(err); - }) - .onInvalidMessageReceived((response, reason) => { - if (!ArraysUtils.equals(messageContent, response.contents)) { - return; - } - - this.handleError(new Error(reason + ': ' + ArraysUtils.toString(response.contents))); - this.listener.unsubscribe(); - }) - .onDecrypt(this.decrypter) - .subscribe(client, msg => { - this.listener.unsubscribe(); - this.receiver(msg); - }); - } - - const tx = new TopicMessageSubmitTransaction().setTopicId(this.topicId).setMessage(messageContent); - - let transactionId; - - try { - const response = await this.buildTransactionFunction(tx).execute(client); - transactionId = response.transactionId; - this.executed = true; - } catch (e) { - this.handleError(e); - if (this.listener) { - this.listener.unsubscribe(); - } - } - - return transactionId; - } - - /** - * Runs validation logic. - * - * @param validator The errors validator. - */ - protected validate(validator: Validator): void { - validator.require(!this.executed, 'This transaction has already been executed.'); - validator.require(!!this.signer || (!!this.message && !!this.message.getSignature()), 'Signing function is missing.'); - validator.require(!!this.buildTransactionFunction, 'Transaction builder is missing.'); - validator.require((!!this.encrypter && !!this.decrypter) || (!this.decrypter && !this.encrypter), 'Either both encrypter and decrypter must be specified or none.') - } -} diff --git a/src/identity/hcs/message.interface.ts b/src/identity/hcs/message.interface.ts deleted file mode 100644 index e61f4e1..0000000 --- a/src/identity/hcs/message.interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Serialize { - toJsonTree: () => any; - toJSON(): () => string; -} - - diff --git a/src/identity/hcs/message.ts b/src/identity/hcs/message.ts deleted file mode 100644 index fcccfdb..0000000 --- a/src/identity/hcs/message.ts +++ /dev/null @@ -1,42 +0,0 @@ -import Long from "long"; -import { Timestamp } from "@hashgraph/sdk"; -import { TimestampUtils } from "../../utils/timestamp-utils"; - -export type Encrypter = (message: T) => T; -export type Decrypter = (message: T, consensusTime: Timestamp) => T; -export type Signer = (message: T) => T; - -export class Message { - private static serialVersionUID = Long.fromInt(1); - - protected timestamp: Timestamp; - - constructor() { - this.timestamp = TimestampUtils.now(); - } - - public getTimestamp(): Timestamp { - return this.timestamp; - } - - public toJsonTree(): any { - const result: any = {}; - result.timestamp = TimestampUtils.toJSON(this.timestamp); - return result; - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - public static fromJsonTree(tree: any, result?: Message): Message { - if (!result) - result = new Message(); - result.timestamp = TimestampUtils.fromJson(tree.timestamp); - return result; - } - - public static fromJson(json: string): Message { - return Message.fromJsonTree(JSON.parse(json)); - } -} diff --git a/src/identity/hcs/serializable-mirror-consensus-response.ts b/src/identity/hcs/serializable-mirror-consensus-response.ts index 7f9e1f8..580c062 100644 --- a/src/identity/hcs/serializable-mirror-consensus-response.ts +++ b/src/identity/hcs/serializable-mirror-consensus-response.ts @@ -19,19 +19,25 @@ export class SerializableMirrorConsensusResponse { } public toString(): string { - return "ConsensusMessage{" - + "consensusTimestamp=" + TimestampUtils.toJSON(this.consensusTimestamp) - + ", message=" + ArraysUtils.toString(this.message) - + ", runningHash=" + ArraysUtils.toString(this.runningHash) - + ", sequenceNumber=" + this.sequenceNumber.toNumber() - + '}'; + return ( + "ConsensusMessage{" + + "consensusTimestamp=" + + TimestampUtils.toJSON(this.consensusTimestamp) + + ", message=" + + ArraysUtils.toString(this.message) + + ", runningHash=" + + ArraysUtils.toString(this.runningHash) + + ", sequenceNumber=" + + this.sequenceNumber.toNumber() + + "}" + ); } public toJsonTree(): any { const result: any = {}; result.consensusTimestamp = { seconds: this.consensusTimestamp.seconds, - nanos: this.consensusTimestamp.nanos + nanos: this.consensusTimestamp.nanos, }; result.message = this.message.toString(); result.runningHash = this.runningHash.toString(); diff --git a/src/identity/hcs/vc/credential-subject.ts b/src/identity/hcs/vc/credential-subject.ts deleted file mode 100644 index 947a84d..0000000 --- a/src/identity/hcs/vc/credential-subject.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { HcsVcDocumentJsonProperties } from "./hcs-vc-document-json-properties"; - -export class CredentialSubject { - protected id: string; - - public getId(): string { - return this.id; - } - - public setId(id: string): void { - this.id = id; - } - - - // JsonClass - - public toJsonTree(): any { - const rootObject = {}; - rootObject[HcsVcDocumentJsonProperties.ID] = this.id; - return rootObject; - } - - public static fromJsonTree(root: any, result?: CredentialSubject): CredentialSubject { - if (!result) - result = new CredentialSubject(); - result.id = root[HcsVcDocumentJsonProperties.ID]; - return result; - - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - public static fromJson(json: string): CredentialSubject { - let result: CredentialSubject; - - try { - const root = JSON.parse(json); - result = this.fromJsonTree(root); - - } catch (e) { - throw new Error('Given JSON string is not a valid CredentialSubject ' + e.message); - } - - return result; - } -} - diff --git a/src/identity/hcs/vc/hcs-vc-document-base.ts b/src/identity/hcs/vc/hcs-vc-document-base.ts deleted file mode 100644 index b20e1c2..0000000 --- a/src/identity/hcs/vc/hcs-vc-document-base.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { Timestamp } from "@hashgraph/sdk"; -import { Hashing } from "../../../utils/hashing"; -import { TimestampUtils } from "../../../utils/timestamp-utils"; -import { HcsDid } from "../did/hcs-did"; -import { JsonClass } from "../json-class"; -import { CredentialSubject } from "./credential-subject"; -import { HcsVcDocumentHashBase } from "./hcs-vc-document-hash-base"; -import { HcsVcDocumentJsonProperties } from "./hcs-vc-document-json-properties"; -import { Issuer } from "./issuer"; - -/** - * The base for a VC document generation in JSON-LD format. - * VC documents according to W3C draft specification must be compatible with JSON-LD version 1.1 Up until now there is - * no Java implementation library of JSON-LD version 1.1. For that reason this object represents only the most basic and - * mandatory attributes from the VC specification and Hedera HCS DID method specification point of view. Applications - * shall extend it with any VC document properties or custom properties they require. - */ -export class HcsVcDocumentBase extends HcsVcDocumentHashBase { - protected context: string[]; - protected credentialSubject: T[]; - - /** - * Creates a new VC Document instance. - */ - constructor() { - super(); - this.context = [HcsVcDocumentJsonProperties.FIRST_CONTEXT_ENTRY]; - } - - /** - * Constructs a credential hash that uniquely identifies this verifiable credential. - * This is not a credential ID, but a hash composed of the properties included in HcsVcDocumentHashBase class - * (excluding issuer name). - * Credential hash is used to find the credential on Hedera VC registry. - * Due to the nature of the VC document the hash taken from the base mandatory fields in this class - * and shall produce a unique constant. - * W3C specification defines ID field of a verifiable credential as not mandatory, however Hedera requires issuers to - * define this property for each VC. - * - * @return The credential hash uniquely identifying this verifiable credential. - */ - public toCredentialHash(): string { - const map = {}; - map[HcsVcDocumentJsonProperties.ID] = this.id; - map[HcsVcDocumentJsonProperties.TYPE] = this.type; - map[HcsVcDocumentJsonProperties.ISSUER] = this.issuer.getId(); - map[HcsVcDocumentJsonProperties.ISSUANCE_DATE] = TimestampUtils.toJSON(this.issuanceDate); - const json: string = JSON.stringify(map); - const hash: Uint8Array = Hashing.sha256.digest(json); - return Hashing.base58.encode(hash); - } - - public getContext(): string[] { - return this.context; - } - - public getId(): string { - return this.id; - } - - public getType(): string[] { - return this.type; - } - - public getIssuer(): Issuer { - return this.issuer; - } - - public getIssuanceDate(): Timestamp { - return this.issuanceDate; - } - - public getCredentialSubject(): T[] { - return this.credentialSubject; - } - - public setId(id: string): void { - this.id = id; - } - - public setIssuer(issuerDid: string): void; - public setIssuer(issuer: Issuer): void; - public setIssuer(issuerDid: HcsDid): void; - public setIssuer(...args: any[]): void { - if (typeof args[0] === 'string') { - this.issuer = new Issuer(args[0]); - return; - } - if (args[0] instanceof Issuer) { - this.issuer = args[0]; - return; - } - if (args[0] instanceof HcsDid) { - this.issuer = new Issuer(args[0].toDid()); - return; - } - } - - public setIssuanceDate(issuanceDate: Timestamp): void { - this.issuanceDate = issuanceDate; - } - - - /** - * Adds an additional context to @context field of the VC document. - * - * @param context The context to add. - */ - public addContext(context: string): void { - this.context.push(context); - } - - /** - * Adds an additional type to `type` field of the VC document. - * - * @param type The type to add. - */ - public addType(type: string): void { - this.type.push(type); - } - - /** - * Adds a credential subject. - * - * @param credentialSubject The credential subject to add. - */ - public addCredentialSubject(credentialSubject: T): void { - if (this.credentialSubject == null) { - this.credentialSubject = []; - } - - this.credentialSubject.push(credentialSubject); - } - - /** - * Checks if all mandatory fields of a VC document are filled in. - * - * @return True if the document is complete and false otherwise. - */ - public isComplete(): boolean { - return ( - (this.context != null) && - (!!this.context.length) && - (HcsVcDocumentJsonProperties.FIRST_CONTEXT_ENTRY == this.context[0]) && - (this.type != null) && - (!!this.type.length) && - (this.type.indexOf(HcsVcDocumentJsonProperties.VERIFIABLE_CREDENTIAL_TYPE) > -1) && - (this.issuanceDate != null) && - (this.issuer != null) && - (!!this.issuer.getId()) && - (this.credentialSubject != null) && - (!!this.credentialSubject.length) - ); - } - - // JsonClass - - public toJsonTree(): any { - const rootObject = super.toJsonTree(); - - const context = []; - if (this.context) { - for (let index = 0; index < this.context.length; index++) { - const element = this.context[index]; - context.push(element); - } - } - rootObject[HcsVcDocumentJsonProperties.CONTEXT] = context; - - const credentialSubject = []; - if (this.credentialSubject) { - for (let index = 0; index < this.credentialSubject.length; index++) { - const element = this.credentialSubject[index]; - credentialSubject.push(element.toJsonTree()); - } - } - rootObject[HcsVcDocumentJsonProperties.CREDENTIAL_SUBJECT] = credentialSubject; - - return rootObject; - } - - public static fromJsonTree(root: any, result?: HcsVcDocumentBase, credentialSubjectClass?: JsonClass): HcsVcDocumentBase { - if (!result) - result = new HcsVcDocumentBase(); - result = HcsVcDocumentHashBase.fromJsonTree(root, result) as HcsVcDocumentBase; - const jsonCredentialSubject = root[HcsVcDocumentJsonProperties.CREDENTIAL_SUBJECT] as any[]; - const credentialSubject: U[] = []; - for (let i = 0; i < jsonCredentialSubject.length; i++) { - const item = jsonCredentialSubject[i]; - const subject: U = credentialSubjectClass.fromJsonTree(item); - credentialSubject.push(subject) - } - result.credentialSubject = credentialSubject; - return result; - } - - /** - * Converts this document into a JSON string. - * - * @return The JSON representation of this document. - */ - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - /** - * Converts a VC document in JSON format into a {@link HcsVcDocumentBase} object. - * Please note this conversion respects only the fields of the base VC document. All other fields are ignored. - * - * @param The type of the credential subject. - * @param json The VC document as JSON string. - * @param credentialSubjectClass The type of the credential subject inside. - * @return The {@link HcsVcDocumentBase} object. - */ - public static fromJson(json: string, credentialSubjectClass?: JsonClass): HcsVcDocumentBase { - let result: HcsVcDocumentBase; - try { - const root = JSON.parse(json); - result = this.fromJsonTree(root, null, credentialSubjectClass); - - } catch (e) { - throw new Error('Given JSON string is not a valid HcsVcDocumentBase ' + e.message); - } - return result; - } -} diff --git a/src/identity/hcs/vc/hcs-vc-document-hash-base.ts b/src/identity/hcs/vc/hcs-vc-document-hash-base.ts deleted file mode 100644 index 94c2d7a..0000000 --- a/src/identity/hcs/vc/hcs-vc-document-hash-base.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Timestamp } from "@hashgraph/sdk"; -import { TimestampUtils } from "../../../utils/timestamp-utils"; -import { HcsVcDocumentJsonProperties } from "./hcs-vc-document-json-properties"; -import { Issuer } from "./issuer"; - -/** - * The part of the VC document that is used for hash calculation. - */ -export class HcsVcDocumentHashBase { - protected id: string; - protected type: string[]; - protected issuer: Issuer; - protected issuanceDate: Timestamp; - - /** - * Creates a new VC document instance. - */ - constructor() { - this.type = [HcsVcDocumentJsonProperties.VERIFIABLE_CREDENTIAL_TYPE]; - } - - // JsonClass - - public toJsonTree(): any { - const rootObject = {}; - if (this.id) - rootObject[HcsVcDocumentJsonProperties.ID] = this.id; - if (this.type) - rootObject[HcsVcDocumentJsonProperties.TYPE] = this.type; - if (this.issuer) - rootObject[HcsVcDocumentJsonProperties.ISSUER] = this.issuer.toJsonTree(); - if (this.issuanceDate) - rootObject[HcsVcDocumentJsonProperties.ISSUANCE_DATE] = TimestampUtils.toJSON(this.issuanceDate); - return rootObject; - } - - public static fromJsonTree(root: any, result?: HcsVcDocumentHashBase): HcsVcDocumentHashBase { - if (!result) - result = new HcsVcDocumentHashBase(); - if (root[HcsVcDocumentJsonProperties.ID]) - result.id = root[HcsVcDocumentJsonProperties.ID]; - if (root[HcsVcDocumentJsonProperties.TYPE]) - result.type = root[HcsVcDocumentJsonProperties.TYPE]; - if (root[HcsVcDocumentJsonProperties.ISSUER]) - result.issuer = Issuer.fromJsonTree(root[HcsVcDocumentJsonProperties.ISSUER]); - if (root[HcsVcDocumentJsonProperties.ISSUANCE_DATE]) - result.issuanceDate = TimestampUtils.fromJson(root[HcsVcDocumentJsonProperties.ISSUANCE_DATE]); - return result; - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - public static fromJson(json: string): HcsVcDocumentHashBase { - let result: HcsVcDocumentHashBase; - try { - const root = JSON.parse(json); - result = this.fromJsonTree(root); - - } catch (e) { - throw new Error('Given JSON string is not a valid HcsVcDocumentHashBase ' + e.message); - } - return result; - } -} \ No newline at end of file diff --git a/src/identity/hcs/vc/hcs-vc-document-json-properties.ts b/src/identity/hcs/vc/hcs-vc-document-json-properties.ts deleted file mode 100644 index 160fc81..0000000 --- a/src/identity/hcs/vc/hcs-vc-document-json-properties.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Key property names in VC document standard. - */ -export module HcsVcDocumentJsonProperties { - export const CONTEXT = '@context'; - export const FIRST_CONTEXT_ENTRY = 'https://www.w3.org/2018/credentials/v1'; - export const ID = 'id'; - export const CREDENTIAL_SUBJECT = 'credentialSubject'; - export const TYPE = 'type'; - export const VERIFIABLE_CREDENTIAL_TYPE = 'VerifiableCredential'; - export const ISSUER = 'issuer'; - export const ISSUANCE_DATE = 'issuanceDate'; - export const CREDENTIAL_STATUS = 'credentialStatus'; - export const PROOF = 'proof'; -} diff --git a/src/identity/hcs/vc/hcs-vc-message.ts b/src/identity/hcs/vc/hcs-vc-message.ts deleted file mode 100644 index 1beca8a..0000000 --- a/src/identity/hcs/vc/hcs-vc-message.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Timestamp } from "@hashgraph/sdk"; -import { Hashing } from "../../../utils/hashing"; -import { Decrypter, Encrypter, Message } from "../message"; -import { MessageEnvelope } from "../message-envelope"; -import { HcsVcOperation } from "./hcs-vc-operation"; - -export class HcsVcMessage extends Message { - private operation: HcsVcOperation; - private credentialHash: string; - - /** - * Creates a new message instance. - * - * @param operation Operation type. - * @param credentialHash Credential hash. - */ - constructor(operation: HcsVcOperation, credentialHash: string) { - super(); - this.operation = operation; - this.credentialHash = credentialHash; - } - - /** - * Checks if the message is valid from content point of view. - * Does not verify hash nor any signatures. - * - * @return True if the message is valid and False otherwise. - */ - public isValid(): boolean { - return (!!this.credentialHash && !!this.operation); - } - - public getOperation(): HcsVcOperation { - return this.operation; - } - - public getCredentialHash(): string { - return this.credentialHash; - } - - public toJsonTree(): any { - const result: any = super.toJsonTree(); - result.operation = this.operation; - result.credentialHash = this.credentialHash; - return result; - } - - public static fromJsonTree(tree: any, result?: HcsVcMessage): HcsVcMessage { - if (!result) { - result = new HcsVcMessage(tree.operation, tree.credentialHash); - } else { - result.operation = tree.operation; - result.credentialHash = tree.credentialHash; - } - result = super.fromJsonTree(tree, result) as HcsVcMessage; - return result; - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - public static fromJson(json: string): Message { - return Message.fromJsonTree(JSON.parse(json)); - } - - /** - * Creates a new VC message for submission to HCS topic. - * - * @param credentialHash VC hash. - * @param operation The operation on a VC document. - * @return The HCS message wrapped in an envelope for the given VC and operation. - */ - public static fromCredentialHash(credentialHash: string, operation: HcsVcOperation): MessageEnvelope { - const message: HcsVcMessage = new HcsVcMessage(operation, credentialHash); - return new MessageEnvelope(message); - } - - /** - * Provides an encryption operator that converts an {@link HcsVcMessage} into encrypted one. - * - * @param encryptionFunction The encryption function to use for encryption of single attributes. - * @return The encryption operator instance. - */ - public static getEncrypter(encryptionFunction: Encrypter): Encrypter { - if (encryptionFunction == null) { - throw "Encryption function is missing or null."; - } - return function (message: HcsVcMessage) { - // Encrypt the credential hash - const encryptedHash: string = encryptionFunction(message.getCredentialHash()); - const hash = Hashing.base64.encode(encryptedHash); - return new HcsVcMessage(message.getOperation(), hash); - }; - } - - /** - * Provides a decryption function that converts {@link HcsVcMessage} in encrypted for into a plain form. - * - * @param decryptionFunction The decryption function to use for decryption of single attributes. - * @return The decryption function for the {@link HcsVcMessage} - */ - public static getDecrypter(decryptionFunction: Decrypter): Decrypter { - if (decryptionFunction == null) { - throw "Decryption function is missing or null."; - } - return function (encryptedMsg: HcsVcMessage, consensusTimestamp: Timestamp) { - // Decrypt DID string - let decryptedHash: string = encryptedMsg.getCredentialHash(); - if (decryptedHash != null) { - const hash: string = Hashing.base64.decode(decryptedHash); - decryptedHash = decryptionFunction(hash, consensusTimestamp); - } - return new HcsVcMessage(encryptedMsg.getOperation(), decryptedHash); - }; - } -} diff --git a/src/identity/hcs/vc/hcs-vc-operation.ts b/src/identity/hcs/vc/hcs-vc-operation.ts deleted file mode 100644 index 167b2a1..0000000 --- a/src/identity/hcs/vc/hcs-vc-operation.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * The operation type to be performed on the DID document. - */ -export enum HcsVcOperation { - ISSUE = 'issue', - REVOKE = 'revoke', - SUSPEND = 'suspend', - RESUME = 'resume' -} diff --git a/src/identity/hcs/vc/hcs-vc-status-resolver.ts b/src/identity/hcs/vc/hcs-vc-status-resolver.ts deleted file mode 100644 index ca026be..0000000 --- a/src/identity/hcs/vc/hcs-vc-status-resolver.ts +++ /dev/null @@ -1,102 +0,0 @@ -import {TopicId} from "@hashgraph/sdk"; -import {TimestampUtils} from "../../../utils/timestamp-utils"; -import {MessageEnvelope} from "../message-envelope"; -import {MessageListener} from "../message-listener"; -import {MessageResolver} from "../message-resolver"; -import {HcsVcMessage} from "./hcs-vc-message"; -import {HcsVcOperation} from "./hcs-vc-operation"; -import {HcsVcTopicListener, PublicKeysProvider} from "./hcs-vc-topic-listener"; - -/** - * Resolves the DID from Hedera network. - */ -export class HcsVcStatusResolver extends MessageResolver { - /** - * A function providing a collection of public keys accepted for a given credential hash. - * If the function is not supplied, the listener will not validate signatures. - */ - private publicKeysProvider: PublicKeysProvider; - - /** - * Instantiates a new status resolver for the given VC topic. - * - * @param topicId The HCS VC topic ID. - */ - constructor(topicId: TopicId); - /** - * Instantiates a new status resolver for the given VC topic with signature validation. - * - * @param topicId The VC consensus topic ID. - * @param publicKeysProvider Provider of a public keys acceptable for a given VC hash. - */ - constructor(topicId: TopicId, publicKeysProvider: PublicKeysProvider); - constructor(...args: any[]) { - const topicId = args[0] as TopicId; - super(topicId); - if (args[1]) { - this.publicKeysProvider = args[1]; - } else { - this.publicKeysProvider = null; - } - } - - /** - * Adds a credential hash to resolve its status. - * - * @param credentialHash The credential hash string. - * @return This resolver instance. - */ - public addCredentialHash(credentialHash: string): HcsVcStatusResolver { - if (credentialHash != null) { - this.results.set(credentialHash, null); - } - return this; - } - - /** - * Adds multiple VC hashes to resolve. - * - * @param hashes The set of VC hash strings. - * @return This resolver instance. - */ - public addCredentialHashes(hashes: string[]): HcsVcStatusResolver { - if (hashes != null) { - hashes.forEach(d => this.addCredentialHash(d)); - } - - return this; - } - - protected override matchesSearchCriteria(message: HcsVcMessage): boolean { - return this.results.has(message.getCredentialHash()); - } - - - protected override supplyMessageListener(): MessageListener { - return new HcsVcTopicListener(this.topicId, this.publicKeysProvider); - } - - protected override processMessage(envelope: MessageEnvelope): void { - const message: HcsVcMessage = envelope.open(); - - // Skip messages that are older than the once collected or if we already have a REVOKED message - const existing: MessageEnvelope = this.results.get(message.getCredentialHash()); - - const chackOperation = ( - (existing != null) && - ( - (TimestampUtils.lessThan(envelope.getConsensusTimestamp(), existing.getConsensusTimestamp())) || - ( - HcsVcOperation.REVOKE == (existing.open().getOperation()) && - HcsVcOperation.REVOKE != (message.getOperation()) - ) - ) - ) - if (chackOperation) { - return; - } - - // Add valid message to the results - this.results.set(message.getCredentialHash(), envelope); - } -} diff --git a/src/identity/hcs/vc/hcs-vc-topic-listener.ts b/src/identity/hcs/vc/hcs-vc-topic-listener.ts deleted file mode 100644 index a21a5dd..0000000 --- a/src/identity/hcs/vc/hcs-vc-topic-listener.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { PublicKey, TopicId, TopicMessage } from "@hashgraph/sdk"; -import { MessageEnvelope } from "../message-envelope"; -import { MessageListener } from "../message-listener"; -import { HcsVcMessage } from "./hcs-vc-message"; - -export type PublicKeysProvider = (t: string) => PublicKey[]; - -/** - * A listener of confirmed {@link HcsVcMessage} messages from a VC topic. - * Messages are received from a given mirror node, parsed and validated. - */ -export class HcsVcTopicListener extends MessageListener { - /** - * A function providing a collection of public keys accepted for a given credential hash. - * If the function is not supplied, the listener will not validate signatures. - */ - private publicKeysProvider: PublicKeysProvider; - - /** - * Creates a new instance of a VC topic listener for the given consensus topic. - * By default, invalid messages are ignored and errors are not. - * Listener without a public key provider will not validate message signatures. - * - * @param vcTopicId The VC consensus topic ID. - */ - constructor(vcTopicId: TopicId) - /** - * Creates a new instance of a VC topic listener for the given consensus topic. - * By default, invalid messages are ignored and errors are not. - * - * @param vcTopicId The VC consensus topic ID. - * @param publicKeysProvider Provider of a public keys acceptable for a given VC hash. - */ - constructor(vcTopicId: TopicId, publicKeysProvider: PublicKeysProvider); - constructor(...args: any[]) { - const vcTopicId = args[0] as TopicId; - super(vcTopicId); - if (args[1]) { - this.publicKeysProvider = args[1]; - } else { - this.publicKeysProvider = null; - } - } - - protected override extractMessage(response: TopicMessage): MessageEnvelope { - let result: MessageEnvelope = null; - try { - result = MessageEnvelope.fromMirrorResponse(response, HcsVcMessage); - } catch (err) { - this.handleError(err); - } - return result; - } - - protected override isMessageValid(envelope: MessageEnvelope, response: TopicMessage): boolean { - try { - const msgDecrypter = !!this.decrypter ? HcsVcMessage.getDecrypter(this.decrypter) : null; - - const message: HcsVcMessage = envelope.open(msgDecrypter); - if (message == null) { - this.reportInvalidMessage(response, "Empty message received when opening envelope"); - return false; - } - - if (!message.isValid()) { - this.reportInvalidMessage(response, "Message content validation failed."); - return false; - } - - // Validate signature only if public key provider has been supplied. - if (!!this.publicKeysProvider && !this.isSignatureAccepted(envelope)) { - this.reportInvalidMessage(response, "Signature validation failed"); - return false; - } - - return true; - } catch (err) { - this.handleError(err); - this.reportInvalidMessage(response, "Exception while validating message: " + err.message); - return false; - } - } - - /** - * Checks if the signature on the envelope is accepted by any public key supplied for the credential hash. - * - * @param envelope The message envelope. - * @return True if signature is accepted, false otherwise. - */ - private isSignatureAccepted(envelope: MessageEnvelope): boolean { - if (!this.publicKeysProvider) { - return false; - } - - const message: HcsVcMessage = envelope.open(); - const acceptedKeys: PublicKey[] = this.publicKeysProvider(message.getCredentialHash()); - if (!acceptedKeys || !acceptedKeys.length) { - return false; - } - - for (let publicKey of acceptedKeys) { - if (envelope.isSignatureValid(publicKey)) { - return true; - } - } - - return false; - } -} diff --git a/src/identity/hcs/vc/hcs-vc-transaction.ts b/src/identity/hcs/vc/hcs-vc-transaction.ts deleted file mode 100644 index 830faec..0000000 --- a/src/identity/hcs/vc/hcs-vc-transaction.ts +++ /dev/null @@ -1,84 +0,0 @@ -import {MessageTransaction} from "../message-transaction"; -import {HcsVcMessage} from "./hcs-vc-message"; -import {HcsVcOperation} from "./hcs-vc-operation"; -import {PublicKey, TopicId} from "@hashgraph/sdk"; -import {MessageEnvelope} from "../message-envelope"; -import {Validator} from "../../../utils/validator"; -import {MessageListener} from "../message-listener"; -import {HcsVcTopicListener} from "./hcs-vc-topic-listener"; -import {Encrypter} from "../message"; - -/** - * The DID document creation, update or deletion transaction. - * Builds a correct {@link HcsDidMessage} and send it to HCS DID topic. - */ -export class HcsVcTransaction extends MessageTransaction { - private operation: HcsVcOperation; - private credentialHash: string; - private signerPublicKey: PublicKey; - - /** - * Instantiates a new transaction object. - * - * @param topicId The HCS VC topic ID where message will be submitted. - * @param operation The operation to be performed on a verifiable credential. - * @param credentialHash The hash of a credential. - * @param signerPublicKey Public key of the signer of this operation. - */ - constructor(topicId: TopicId, operation: HcsVcOperation, credentialHash: string, signerPublicKey: PublicKey); - - /** - * Instantiates a new transaction object from a message that was already prepared. - * - * @param topicId The HCS VC topic ID where message will be submitted. - * @param message The message envelope. - * @param signerPublicKey Public key of the signer of this operation. - */ - constructor(topicId: TopicId, message: MessageEnvelope, signerPublicKey: PublicKey); - constructor(...args) { - if ( - (args.length === 4) && - (args[0] instanceof TopicId) && - // (args[1] instanceof HcsVcOperation) && - (typeof args[2] === 'string') && - (args[3] instanceof PublicKey) - ) { - const [topicId, operation, credentialHash, signerPublicKey] = args; - super(topicId); - this.operation = operation; - this.credentialHash = credentialHash; - this.signerPublicKey = signerPublicKey; - } else if ( - (args.length === 3) && - (args[0] instanceof TopicId) && - (args[1] instanceof MessageEnvelope) && - (args[2] instanceof PublicKey) - ) { - const [topicId, message, signerPublicKey] = args; - super(topicId, message); - this.signerPublicKey = signerPublicKey; - this.operation = null; - this.credentialHash = null; - } - } - - protected validate(validator: Validator): void { - super.validate(validator); - validator.require(!!this.credentialHash || !!this.message, 'Verifiable credential hash is null or empty.'); - validator.require(!!this.operation || !!this.message, 'Operation on verifiable credential is not defined.'); - } - - protected buildMessage(): MessageEnvelope { - return HcsVcMessage.fromCredentialHash(this.credentialHash, this.operation); - } - - protected provideTopicListener(topicIdToListen: TopicId): MessageListener { - return new HcsVcTopicListener(topicIdToListen, (s) => { - return [this.signerPublicKey] - }); - } - - protected provideMessageEncrypter(encryptionFunction: Encrypter): (input: HcsVcMessage) => HcsVcMessage { - return HcsVcMessage.getEncrypter(encryptionFunction); - } -} diff --git a/src/identity/hcs/vc/issuer.ts b/src/identity/hcs/vc/issuer.ts deleted file mode 100644 index 4763aad..0000000 --- a/src/identity/hcs/vc/issuer.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { HcsVcDocumentJsonProperties } from "./hcs-vc-document-json-properties"; - -export class Issuer { - protected id: string; - protected name: string; - - constructor(id: string) - constructor(id: string, name: string); - constructor(...args: any[]) { - this.id = args[0]; - this.name = args[1] || null; - } - - public getId(): string { - return this.id; - } - - public getName(): string { - return this.name; - } - - // JsonClass - - public toJsonTree(): any { - if (this.name) { - const rootObject = {}; - rootObject[HcsVcDocumentJsonProperties.ID] = this.id; - rootObject['name'] = this.name; - return rootObject; - } - return this.id; - } - - public static fromJsonTree(root: any, result?: Issuer): Issuer { - let id: string, name: string; - if (typeof root == "string") { - id = root; - } else { - id = root[HcsVcDocumentJsonProperties.ID]; - name = root["name"]; - } - if (result) { - result.id = id; - result.name = name - return result; - } else { - return new Issuer(id, name); - } - } - - public toJSON(): string { - return JSON.stringify(this.toJsonTree()); - } - - public static fromJson(json: string): Issuer { - let result: Issuer; - - try { - const root = JSON.parse(json); - result = this.fromJsonTree(root); - - } catch (e) { - throw new Error('Given JSON string is not a valid Issuer ' + e.message); - } - - return result; - } -} \ No newline at end of file diff --git a/src/identity/hedera-did.ts b/src/identity/hedera-did.ts deleted file mode 100644 index bc8ae6d..0000000 --- a/src/identity/hedera-did.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {DidDocumentBase} from "./did-document-base"; -import {DidSyntax} from "./did-syntax"; - -export interface HederaDid { - // fromString(string): HederaDid; - toDid(): string; - generateDidDocument(): DidDocumentBase; - getNetwork(): string; - getMethod(): DidSyntax.Method -} diff --git a/src/index.ts b/src/index.ts index f35c83d..1e92092 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,75 +1,72 @@ -import {AddressBook} from "./identity/hcs/address-book"; -import {ArraysUtils} from "./utils/arrays-utils"; -import {CredentialSubject} from "./identity/hcs/vc/credential-subject"; -import {DidDocumentBase} from "./identity/did-document-base"; -import {DidDocumentJsonProperties} from "./identity/did-document-json-properties"; -import {DidMethodOperation} from "./identity/did-method-operation"; -import {DidParser} from "./identity/did-parser"; -import {DidSyntax} from "./identity/did-syntax"; -import {Hashing} from "./utils/hashing"; -import {HcsDidMessage} from "./identity/hcs/did/hcs-did-message"; -import {HcsDidResolver} from "./identity/hcs/did/hcs-did-resolver"; -import {HcsDidRootKey} from "./identity/hcs/did/hcs-did-root-key"; -import {HcsDidTopicListener} from "./identity/hcs/did/hcs-did-topic-listener"; -import {HcsDidTransaction} from "./identity/hcs/did/hcs-did-transaction"; -import {HcsDid} from "./identity/hcs/did/hcs-did"; -import {HcsIdentityNetworkBuilder} from "./identity/hcs/hcs-identity-network-builder"; -import {HcsIdentityNetwork} from "./identity/hcs/hcs-identity-network"; -import {HcsVcDocumentBase} from "./identity/hcs/vc/hcs-vc-document-base"; -import {HcsVcDocumentHashBase} from "./identity/hcs/vc/hcs-vc-document-hash-base"; -import {HcsVcDocumentJsonProperties} from "./identity/hcs/vc/hcs-vc-document-json-properties"; -import {HcsVcMessage} from "./identity/hcs/vc/hcs-vc-message"; -import {HcsVcOperation} from "./identity/hcs/vc/hcs-vc-operation"; -import {HcsVcStatusResolver} from "./identity/hcs/vc/hcs-vc-status-resolver"; -import {HcsVcTopicListener} from "./identity/hcs/vc/hcs-vc-topic-listener"; -import {HederaDid} from "./identity/hedera-did"; -import {JsonClass} from "./identity/hcs/json-class"; -import {MessageEnvelope} from "./identity/hcs/message-envelope"; -import {MessageListener} from "./identity/hcs/message-listener"; -import {MessageMode} from "./identity/hcs/message-mode"; -import {MessageResolver} from "./identity/hcs/message-resolver"; -import {MessageTransaction} from "./identity/hcs/message-transaction"; -import {Message} from "./identity/hcs/message"; -import {SerializableMirrorConsensusResponse} from "./identity/hcs/serializable-mirror-consensus-response"; -import {TimestampUtils} from "./utils/timestamp-utils"; -import {Validator} from "./utils/validator"; -import {Issuer} from "./identity/hcs/vc/issuer"; +import { DidDocument } from "./identity/did-document"; +import { DidDocumentJsonProperties } from "./identity/did-document-json-properties"; +import { DidError, DidErrorCode } from "./identity/did-error"; +import { DidMethodOperation } from "./identity/did-method-operation"; +import { DidParser } from "./identity/did-parser"; +import { HederaDidResolver } from "./identity/did-resolver"; +import { DidSyntax } from "./identity/did-syntax"; +import { HcsDidCreateDidDocumentEvent } from "./identity/hcs/did/event/document/hcs-did-create-did-document-event"; +import { HcsDidDeleteEvent } from "./identity/hcs/did/event/document/hcs-did-delete-event"; +import { HcsDidEventTargetName } from "./identity/hcs/did/event/hcs-did-event-target-name"; +import { HcsDidCreateDidOwnerEvent } from "./identity/hcs/did/event/owner/hcs-did-create-did-owner-event"; +import { HcsDidUpdateDidOwnerEvent } from "./identity/hcs/did/event/owner/hcs-did-update-did-owner-event"; +import { HcsDidCreateServiceEvent } from "./identity/hcs/did/event/service/hcs-did-create-service-event"; +import { HcsDidRevokeServiceEvent } from "./identity/hcs/did/event/service/hcs-did-revoke-service-event"; +import { HcsDidUpdateServiceEvent } from "./identity/hcs/did/event/service/hcs-did-update-service-event"; +import { HcsDidCreateVerificationMethodEvent } from "./identity/hcs/did/event/verification-method/hcs-did-create-verification-method-event"; +import { HcsDidRevokeVerificationMethodEvent } from "./identity/hcs/did/event/verification-method/hcs-did-revoke-verification-method-event"; +import { HcsDidUpdateVerificationMethodEvent } from "./identity/hcs/did/event/verification-method/hcs-did-update-verification-method-event"; +import { HcsDidCreateVerificationRelationshipEvent } from "./identity/hcs/did/event/verification-relationship/hcs-did-create-verification-relationship-event"; +import { HcsDidRevokeVerificationRelationshipEvent } from "./identity/hcs/did/event/verification-relationship/hcs-did-revoke-verification-relationship-event"; +import { HcsDidUpdateVerificationRelationshipEvent } from "./identity/hcs/did/event/verification-relationship/hcs-did-update-verification-relationship-event"; +import { HcsDid } from "./identity/hcs/did/hcs-did"; +import { HcsDidEventMessageResolver } from "./identity/hcs/did/hcs-did-event-message-resolver"; +import { HcsDidMessage } from "./identity/hcs/did/hcs-did-message"; +import { HcsDidTopicListener } from "./identity/hcs/did/hcs-did-topic-listener"; +import { HcsDidTransaction } from "./identity/hcs/did/hcs-did-transaction"; +import { JsonClass } from "./identity/hcs/json-class"; +import { MessageEnvelope } from "./identity/hcs/message-envelope"; +import { SerializableMirrorConsensusResponse } from "./identity/hcs/serializable-mirror-consensus-response"; +import { ArraysUtils } from "./utils/arrays-utils"; +import { Ed25519PubCodec } from "./utils/ed25519PubCodec"; +import { Hashing } from "./utils/hashing"; +import { TimestampUtils } from "./utils/timestamp-utils"; +import { Validator } from "./utils/validator"; export { - AddressBook, ArraysUtils, - CredentialSubject, - DidDocumentBase, + DidDocument, DidDocumentJsonProperties, + DidError, + DidErrorCode, DidMethodOperation, DidParser, DidSyntax, + Ed25519PubCodec, Hashing, HcsDid, + HcsDidCreateDidDocumentEvent, + HcsDidCreateDidOwnerEvent, + HcsDidCreateServiceEvent, + HcsDidCreateVerificationMethodEvent, + HcsDidCreateVerificationRelationshipEvent, + HcsDidDeleteEvent, + HcsDidEventMessageResolver, + HcsDidEventTargetName, HcsDidMessage, - HcsDidResolver, - HcsDidRootKey, + HcsDidRevokeServiceEvent, + HcsDidRevokeVerificationMethodEvent, + HcsDidRevokeVerificationRelationshipEvent, HcsDidTopicListener, HcsDidTransaction, - HcsIdentityNetwork, - HcsIdentityNetworkBuilder, - HcsVcDocumentBase, - HcsVcDocumentHashBase, - HcsVcDocumentJsonProperties, - HcsVcMessage, - HcsVcOperation, - HcsVcStatusResolver, - HcsVcTopicListener, - HederaDid, + HcsDidUpdateDidOwnerEvent, + HcsDidUpdateServiceEvent, + HcsDidUpdateVerificationMethodEvent, + HcsDidUpdateVerificationRelationshipEvent, + HederaDidResolver, JsonClass, - Message, MessageEnvelope, - MessageListener, - MessageMode, - MessageResolver, - MessageTransaction, SerializableMirrorConsensusResponse, TimestampUtils, Validator, - Issuer -} +}; diff --git a/src/utils/arrays-utils.ts b/src/utils/arrays-utils.ts index 9b13972..4e8b3d1 100644 --- a/src/utils/arrays-utils.ts +++ b/src/utils/arrays-utils.ts @@ -1,14 +1,13 @@ - export class ArraysUtils { public static equals(a: Uint8Array, b: Uint8Array): boolean { if (a == b) { - return true + return true; } if (!a || !b) { - return false + return false; } if (a.length != b.length) { - return false + return false; } for (let i = 0; i < a.length; i++) { if (a[i] != b[i]) return false; @@ -21,6 +20,6 @@ export class ArraysUtils { } public static fromString(text: string): Uint8Array { - return new Uint8Array(Buffer.from(text, "utf8")) + return new Uint8Array(Buffer.from(text, "utf8")); } } diff --git a/src/utils/ed25519PubCodec.ts b/src/utils/ed25519PubCodec.ts new file mode 100644 index 0000000..54d5490 --- /dev/null +++ b/src/utils/ed25519PubCodec.ts @@ -0,0 +1,65 @@ +// @ts-check + +import { BlockCodec, ByteView } from "multiformats/codecs/interface"; +import varint from "varint"; + +/** + * Ed25519PubCodec MULTICODEC(public-key-type, raw-public-key-bytes) + * https://github.com/multiformats/js-multiformats#multicodec-encoders--decoders--codecs + * Implementation of BlockCodec interface which implements both BlockEncoder and BlockDecoder. + * @template T + * @typedef {import('./interface').ByteView} ByteView + */ + +export class Ed25519PubCodec implements BlockCodec { + // values retrieved from https://raw.githubusercontent.com/multiformats/multicodec/master/table.csv + name: string = "ed25519-pub"; + code: number = 0xed; + encode(data: Uint8Array): ByteView { + const prefix = this.varintEncode(this.code); + return this.concat([prefix, data], prefix.length + data.length); + } + decode(bytes: ByteView): Uint8Array { + return this.rmPrefix(bytes); + } + + /** + * Returns a new Uint8Array created by concatenating the passed ArrayLikes + * + * @param {Array>} arrays + * @param {number} [length] + */ + private concat(arrays: Array>, length: number) { + if (!length) { + length = arrays.reduce((acc, curr) => acc + curr.length, 0); + } + + const output = new Uint8Array(length); + let offset = 0; + + for (const arr of arrays) { + output.set(arr, offset); + offset += arr.length; + } + + return output; + } + + /** + * @param {number} num + */ + private varintEncode(num: number) { + return Uint8Array.from(varint.encode(num)); + } + + /** + * Decapsulate the multicodec-packed prefix from the data. + * + * @param {Uint8Array} data + * @returns {Uint8Array} + */ + private rmPrefix(data: Uint8Array): Uint8Array { + varint.decode(/** @type {Buffer} */ data); + return data.slice(varint.decode.bytes); + } +} diff --git a/src/utils/hashing.ts b/src/utils/hashing.ts index 273e951..7a9ae8d 100644 --- a/src/utils/hashing.ts +++ b/src/utils/hashing.ts @@ -1,32 +1,50 @@ +import * as Base58 from "base58-js"; import * as crypto from "crypto"; -import bs58 from "bs58"; import { Base64 } from "js-base64"; +import { base58btc } from "multiformats/bases/base58"; +import { MultibaseDecoder, MultibaseEncoder } from "multiformats/bases/interface"; export class Hashing { - public static readonly base58 = { - encode: function (data: Uint8Array): string { - return bs58.encode(data); - }, - decode: function (data: string): Uint8Array { - return bs58.decode(data); - } - } public static readonly sha256 = { digest: function (data: Uint8Array | string): Uint8Array { const sha256 = crypto - .createHash('sha256') // may need to change in the future. + .createHash("sha256") // may need to change in the future. .update(data) .digest(); return sha256; - } - } + }, + }; public static readonly base64 = { decode: function (encodedString: string): string { - return Base64.fromBase64(encodedString);; + return Base64.fromBase64(encodedString); }, encode: function (decodedBytes: string): string { return Base64.toBase64(decodedBytes); - } - } + }, + }; + + public static readonly base58 = { + decode: function (encodedString: string): Uint8Array { + return Base58.base58_to_binary(encodedString); + }, + encode: function (decodedBytes: Uint8Array): string { + return Base58.binary_to_base58(decodedBytes); + }, + }; + + /** + * @returns Multibase [MULTIBASE] base58-btc encoded value that is a concatenation of the + * MULTIBASE(base58-btc, raw-public-key-bytes) + * https://github.com/multiformats/multibase + * https://www.w3.org/TR/did-core/#dfn-publickeymultibase + */ + public static readonly multibase = { + encode: function (data: Uint8Array, base: MultibaseEncoder = base58btc): string { + return base.encode(data); + }, + decode: function (data: string, base: MultibaseDecoder = base58btc): Uint8Array { + return base.decode(data); + }, + }; } diff --git a/src/utils/ipfs.ts b/src/utils/ipfs.ts new file mode 100644 index 0000000..1d22607 --- /dev/null +++ b/src/utils/ipfs.ts @@ -0,0 +1,22 @@ +import fetch from "node-fetch"; +import { HcsDidCreateDidDocumentEvent } from "../identity/hcs/did/event/document/hcs-did-create-did-document-event"; + +const IPFS_IO_HTTP_PROXY = "https://ipfs.io/ipfs/"; + +export class IpfsDidDocumentDownloader { + constructor(private readonly ipfsHttpProxy: string = IPFS_IO_HTTP_PROXY) {} + + async downloadDocument(docEvent: HcsDidCreateDidDocumentEvent) { + const url = docEvent.getUrl() ?? `${this.ipfsHttpProxy}/${docEvent.getCid}`; + + const result = await fetch(url); + if (!result.ok) { + throw new Error(`DID document could not be fetched from URL: ${url}`); + } + try { + return await result.json(); + } catch (err) { + throw new Error(`DID document from URL could not be parsed as JSON: ${url}`); + } + } +} diff --git a/src/utils/sleep.ts b/src/utils/sleep.ts deleted file mode 100644 index 77ff00e..0000000 --- a/src/utils/sleep.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function Sleep(sleepTime: number): Promise { - return new Promise(resolve => { - setTimeout(() => { - resolve(); - }, sleepTime) - }) -} diff --git a/src/utils/timestamp-utils.ts b/src/utils/timestamp-utils.ts index e8e762b..f1cfd42 100644 --- a/src/utils/timestamp-utils.ts +++ b/src/utils/timestamp-utils.ts @@ -1,5 +1,5 @@ import { Timestamp } from "@hashgraph/sdk"; -import moment from 'moment'; +import moment from "moment"; export class TimestampUtils { public static ISO = "YYYY-MM-DDTHH:mm:ss.SSS[Z]"; @@ -41,4 +41,4 @@ export class TimestampUtils { } a.seconds.lessThan(b.seconds); } -} \ No newline at end of file +} diff --git a/src/utils/validator.ts b/src/utils/validator.ts index 0b73080..dc27945 100644 --- a/src/utils/validator.ts +++ b/src/utils/validator.ts @@ -1,3 +1,5 @@ +import { DidError } from "../identity/did-error"; + export class Validator { protected validationErrors: string[]; @@ -20,7 +22,7 @@ export class Validator { const errors = this.validationErrors; this.validationErrors = null; - throw new Error(prologue + ':\n' + errors.join('\n')); + throw new DidError(prologue + ":\n" + errors.join("\n")); } public require(condition: boolean, errorMessage: string): void { diff --git a/test/aes-encryption-util.js b/test/aes-encryption-util.js deleted file mode 100644 index 41d7250..0000000 --- a/test/aes-encryption-util.js +++ /dev/null @@ -1,15 +0,0 @@ -const crypto = require('crypto'); - -const encrypt = function (plainText, key, outputEncoding = "base64") { - const cipher = crypto.createCipheriv("aes-128-ecb", crypto.createHash('sha256').update(String(key)).digest('base64').substr(0, 16), null); - return Buffer.concat([cipher.update(plainText, 'utf8'), cipher.final()]).toString(outputEncoding); -} - -const decrypt = function (cipherText, key, outputEncoding = "utf8") { - const cipher = crypto.createDecipheriv("aes-128-ecb", crypto.createHash('sha256').update(String(key)).digest('base64').substr(0, 16), null); - return Buffer.concat([cipher.update(cipherText, 'base64'), cipher.final()]).toString(outputEncoding); - -} - -exports.encrypt = encrypt; -exports.decrypt = decrypt; \ No newline at end of file diff --git a/test/did-document-base.js b/test/did-document-base.js deleted file mode 100644 index a71246e..0000000 --- a/test/did-document-base.js +++ /dev/null @@ -1,144 +0,0 @@ -const { - HcsDid, - DidDocumentBase, - DidDocumentJsonProperties, - DidSyntax, - HcsDidRootKey -} = require("../dist"); -const {FileId} = require("@hashgraph/sdk"); -const bs58 = require('bs58'); -const {expect, assert} = require('chai'); - -const network = 'testnet'; - -describe("DidDocumentBase", function() { - it('Test Serialization', async function() { - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, FileId.fromString('0.0.1')); - const doc = did.generateDidDocument(); - - const didJson = doc.toJSON(); - - const root = JSON.parse(didJson); - - expect(root).to.have.keys([ - DidDocumentJsonProperties.CONTEXT, - DidDocumentJsonProperties.ID, - DidDocumentJsonProperties.PUBLIC_KEY, - DidDocumentJsonProperties.AUTHENTICATION, - ]); - assert.equal(root[DidDocumentJsonProperties.CONTEXT], DidSyntax.DID_DOCUMENT_CONTEXT); - assert.equal(root[DidDocumentJsonProperties.ID], did.toDid()); - - const didRootKey = root[DidDocumentJsonProperties.PUBLIC_KEY][0]; - assert.equal(didRootKey['type'], HcsDidRootKey.DID_ROOT_KEY_TYPE); - assert.equal(didRootKey[DidDocumentJsonProperties.ID], did.toDid() + HcsDidRootKey.DID_ROOT_KEY_NAME); - assert.equal(didRootKey['controller'], did.toDid()); - assert.equal(didRootKey['publicKeyBase58'], bs58.encode(privateKey.publicKey.toBytes())); - }); - - it('Test Deserialization', async function() { - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, FileId.fromString('0.0.1')); - const doc = did.generateDidDocument(); - - const didJson = doc.toJSON(); - - const parsedDoc = DidDocumentBase.fromJson(didJson); - assert.equal(parsedDoc.getId(), doc.getId()); - - const didRootKey = parsedDoc.getDidRootKey(); - assert.exists(didRootKey); - assert.equal(didRootKey.getPublicKeyBase58(), doc.getDidRootKey().getPublicKeyBase58()); - assert.equal(didRootKey.getController(), doc.getDidRootKey().getController()); - assert.equal(didRootKey.getId(), doc.getDidRootKey().getId()); - assert.equal(didRootKey.getType(), doc.getDidRootKey().getType()); - }); - - it('Test Invalid Deserialization', async function() { - const didJson = "{" - + " \"@context\": \"https://www.w3.org/ns/did/v1\"," - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1\"," - + " \"authentication\": [" - + " \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#did-root-key\"" - + " ]," - + " \"publicKey\":\"invalidPublicKey\"," - + " \"service\": [" - + " {" - + " \"id\":\"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#vcs\"," - + " \"type\": \"VerifiableCredentialService\"," - + " \"serviceEndpoint\": \"https://example.com/vc/\"" - + " }" - + " ]" - + "}"; - - assert.throw(() => { - DidDocumentBase.fromJson(didJson); - }); - }); - - it('Test Incomplete Json Deserialization', async function() { - const didJsonMissingPublicKeys = "{" - + " \"@context\": \"https://www.w3.org/ns/did/v1\"," - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1\"," - + " \"authentication\": [" - + " \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#did-root-key\"" - + " ]" - + "}"; - - const didJsonMissingRootKey = "{" - + " \"@context\": \"https://www.w3.org/ns/did/v1\"," - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1\"," - + " \"authentication\": [" - + " \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#did-root-key\"" - + " ]," - + " \"publicKey\": [" - + " {" - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#key-1\"," - + " \"type\": \"Ed25519VerificationKey2018\"," - + " \"publicKeyBase58\": \"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV\"" - + " }" - + " ]," - + " \"service\": [" - + " {" - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#vcs\"," - + " \"type\": \"VerifiableCredentialService\"," - + " \"serviceEndpoint\": \"https://example.com/vc/\"" - + " }" - + " ]" - + "}"; - - const didJsonMissingPublicKeyId = "{" - + " \"@context\": \"https://www.w3.org/ns/did/v1\"," - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1\"," - + " \"authentication\": [" - + " \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#did-root-key\"" - + " ]," - + " \"publicKey\": [" - + " {" - + " \"type\": \"Ed25519VerificationKey2018\"," - + " \"publicKeyBase58\": \"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV\"" - + " }" - + " ]," - + " \"service\": [" - + " {" - + " \"id\": \"did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.1#vcs\"," - + " \"type\": \"VerifiableCredentialService\"," - + " \"serviceEndpoint\": \"https://example.com/vc/\"" - + " }" - + " ]" - + "}"; - - let doc = DidDocumentBase.fromJson(didJsonMissingPublicKeys); - assert.exists(doc); - assert.notExists(doc.getDidRootKey()); - - doc = DidDocumentBase.fromJson(didJsonMissingRootKey); - assert.exists(doc); - assert.notExists(doc.getDidRootKey()); - - doc = DidDocumentBase.fromJson(didJsonMissingPublicKeyId); - assert.exists(doc); - assert.notExists(doc.getDidRootKey()); - }); -}); diff --git a/test/did/hcs-did-message.js b/test/did/hcs-did-message.js deleted file mode 100644 index 96e3629..0000000 --- a/test/did/hcs-did-message.js +++ /dev/null @@ -1,120 +0,0 @@ -const {encrypt, decrypt} = require("../aes-encryption-util"); -const { - FileId, - TopicId, -} = require('@hashgraph/sdk'); -const { - HcsDidMessage, - MessageEnvelope, - DidMethodOperation, - HcsDid, - ArraysUtils -} = require("../../dist"); - -const {assert} = require('chai'); - -const network = 'network'; -const ADDRESS_BOOK_FID = FileId.fromString('0.0.1'); -const DID_TOPIC_ID1 = TopicId.fromString('0.0.2'); -const DID_TOPIC_ID2 = TopicId.fromString('0.0.3'); - -describe('HcsDidMessage', function() { - it('Test Valid Message', async function() { - const privateKey = HcsDid.generateDidRootKey(); - - const did = new HcsDid(network, privateKey.publicKey, ADDRESS_BOOK_FID); - const doc = did.generateDidDocument(); - const didJson = doc.toJSON(); - const originalEnvelope = HcsDidMessage.fromDidDocumentJson(didJson, DidMethodOperation.CREATE); - const message = originalEnvelope.sign(msg => privateKey.sign(msg)); - - const envelope = MessageEnvelope.fromJson(Buffer.from(message).toString("utf8"), HcsDidMessage); - - assert.isTrue(envelope.isSignatureValid(e => e.open().extractDidRootKey())); - assert.isTrue(envelope.open().isValid(DID_TOPIC_ID1)); - assert.deepEqual(originalEnvelope.open().getTimestamp(), envelope.open().getTimestamp()); - }); - - it('Test Encrypted Message', async function() { - const secret = 'Secret encryption password'; - - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, ADDRESS_BOOK_FID); - const doc = did.generateDidDocument(); - const didJson = doc.toJSON(); - - const originalEnvelope = HcsDidMessage.fromDidDocumentJson(didJson, DidMethodOperation.CREATE); - const encryptedMsg = originalEnvelope.encrypt(HcsDidMessage.getEncrypter(m => encrypt(m, secret))); - const encryptedSignedMsg = MessageEnvelope.fromJson(ArraysUtils.toString(encryptedMsg.sign(m => privateKey.sign(m))), HcsDidMessage); - - assert.exists(encryptedSignedMsg); - assert.throw(() => {encryptedSignedMsg.open()}); - - const decryptedMsg = await encryptedSignedMsg.open(HcsDidMessage.getDecrypter((m, t) => decrypt(m, secret))); - - assert.exists(decryptedMsg); - assert.equal(originalEnvelope.open().getDidDocumentBase64(), decryptedMsg.getDidDocumentBase64()); - assert.equal(originalEnvelope.open().getDid(), decryptedMsg.getDid()); - }); - - it('Test Invalid Did', async function() { - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, ADDRESS_BOOK_FID); - const doc = did.generateDidDocument(); - - const didJson = doc.toJSON(); - const message = HcsDidMessage.fromDidDocumentJson(didJson, DidMethodOperation.CREATE).sign(msg => privateKey.sign(msg)); - const msg = MessageEnvelope.fromJson(Buffer.from(message).toString("utf8"), HcsDidMessage).open(); - - const differentDid = new HcsDid(network, HcsDid.generateDidRootKey().publicKey, ADDRESS_BOOK_FID); - msg.did = differentDid.toDid(); - - assert.isFalse(msg.isValid()); - }); - - it('Test Invalid Topic', async function() { - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, ADDRESS_BOOK_FID, DID_TOPIC_ID1); - const doc = did.generateDidDocument(); - - const didJson = doc.toJSON(); - const message = HcsDidMessage.fromDidDocumentJson(didJson, DidMethodOperation.CREATE).sign(msg => privateKey.sign(msg)); - const msg = await MessageEnvelope.fromJson(Buffer.from(message).toString("utf8"), HcsDidMessage).open(); - - assert.isTrue(msg.isValid(DID_TOPIC_ID1)); - assert.isFalse(msg.isValid(DID_TOPIC_ID2)); - }); - - it('Test Missing Data', async function() { - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, ADDRESS_BOOK_FID, DID_TOPIC_ID1); - const doc = did.generateDidDocument(); - const operation = DidMethodOperation.CREATE; - - const didJson = doc.toJSON(); - const message = HcsDidMessage.fromDidDocumentJson(didJson, DidMethodOperation.CREATE).sign(msg => privateKey.sign(msg)); - - const validMsg = MessageEnvelope.fromJson(Buffer.from(message).toString("utf8"), HcsDidMessage).open(); - - let msg = new HcsDidMessage(operation, null, validMsg.getDidDocumentBase64()); - assert.isFalse(msg.isValid()); - - msg = new HcsDidMessage(operation, validMsg.getDid(), null); - assert.isFalse(msg.isValid()); - assert.notExists(msg.getDidDocument()); - assert.exists(msg.getDid()); - assert.equal(operation, msg.getOperation()); - }); - - it('Test Invalid Signature', async function() { - const privateKey = HcsDid.generateDidRootKey(); - const did = new HcsDid(network, privateKey.publicKey, ADDRESS_BOOK_FID, DID_TOPIC_ID1); - const doc = did.generateDidDocument(); - - const didJson = doc.toJSON(); - const message = HcsDidMessage.fromDidDocumentJson(didJson, DidMethodOperation.CREATE).sign(msg => HcsDid.generateDidRootKey().sign(msg)); - const envelope = MessageEnvelope.fromJson(Buffer.from(message).toString("utf8"), HcsDidMessage); - - assert.isFalse(envelope.isSignatureValid(e => e.open().extractDidRootKey())); - }); -}); diff --git a/test/did/hcs-did-method-operations.js b/test/did/hcs-did-method-operations.js deleted file mode 100644 index dbc4891..0000000 --- a/test/did/hcs-did-method-operations.js +++ /dev/null @@ -1,151 +0,0 @@ -const {DidMethodOperation, DidDocumentJsonProperties} = require("../../dist"); -const {NetworkReadyTestBase} = require("../network-ready-test-base"); - -const {assert} = require('chai'); - -const testBase = new NetworkReadyTestBase(); - -let hcsDid, - didDocument; - -const EXPECT_NO_ERROR = function(err) { - throw err; -} - -describe('Hcs Did Method Operations', function() { - before(async function() { - this.timeout(60000); - await testBase.setup(); - hcsDid = testBase.didNetwork.generateDid(false); - didDocument = hcsDid.generateDidDocument().toJSON(); - }); - - after(async function() { - testBase.cleanup(); - }); - - it('Test Create', async function() { - this.timeout(60000); - const op = DidMethodOperation.CREATE; - - const envelope = await testBase.sendDidTransaction(hcsDid, didDocument, op, EXPECT_NO_ERROR); - assert.exists(envelope); - - const msg = envelope.open(); - assert.exists(msg); - assert.exists(msg.getDidDocument()); - - assert.equal(hcsDid.toDid(), msg.getDid()); - assert.isTrue(msg.isValid()); - assert.equal(DidMethodOperation.CREATE, msg.getOperation()); - }); - - it('Test Resolve After Create', async function() { - this.timeout(60000); - const didString = hcsDid.toDid(); - - const envelope = await testBase.resolveDid(didString, EXPECT_NO_ERROR); - const msg = envelope.open(); - - assert.exists(msg); - assert.equal(didString, msg.getDid()); - assert.isTrue(msg.isValid()); - assert.equal(DidMethodOperation.CREATE, msg.getOperation()); - }); - - it('Test Update', async function() { - this.timeout(60000); - const rootObject = JSON.parse(didDocument); - - const publicKeys = rootObject[DidDocumentJsonProperties.PUBLIC_KEY]; - publicKeys.push(JSON.parse("{" - + "\"id\": \"did:example:123456789abcdefghi#keys-2\"," - + "\"type\": \"Ed25519VerificationKey2018\"," - + "\"controller\": \"did:example:pqrstuvwxyz0987654321\"," - + "\"publicKeyBase58\": \"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV\"" - + "}")); - rootObject[DidDocumentJsonProperties.PUBLIC_KEY] = publicKeys; - - const newDoc = JSON.stringify(rootObject); - - const operation = DidMethodOperation.UPDATE; - const envelope = await testBase.sendDidTransaction(hcsDid, newDoc, operation, EXPECT_NO_ERROR); - assert.exists(envelope); - - const msg = envelope.open(); - - assert.exists(msg); - assert.equal(newDoc, msg.getDidDocument()); - assert.equal(operation, msg.getOperation()); - }); - - it('Test Resolve After Update', async function() { - this.timeout(60000); - const didString = hcsDid.toDid(); - - const envelope = await testBase.resolveDid(didString, EXPECT_NO_ERROR); - assert.exists(envelope); - - const msg = envelope.open(); - - assert.exists(msg); - assert.equal(didString, msg.getDid()); - assert.isTrue(msg.isValid()); - assert.equal(DidMethodOperation.UPDATE, msg.getOperation()); - assert.notEqual(didDocument, msg.getDidDocument()); - }); - - it('Test Delete', async function() { - this.timeout(60000); - const rootObject = JSON.parse(didDocument); - - if(rootObject.hasOwnProperty(DidDocumentJsonProperties.AUTHENTICATION)) { - rootObject[DidDocumentJsonProperties.AUTHENTICATION] = []; - } - - const deletedDoc = JSON.stringify(rootObject); - - const operation = DidMethodOperation.DELETE; - const envelope = await testBase.sendDidTransaction(hcsDid, deletedDoc, operation, EXPECT_NO_ERROR); - assert.exists(envelope); - - const msg = envelope.open(); - - assert.exists(msg); - assert.equal(deletedDoc, msg.getDidDocument()); - assert.equal(operation, msg.getOperation()); - }); - - it('Test Resolve After Delete', async function() { - this.timeout(60000); - const didString = hcsDid.toDid(); - - const envelope = await testBase.resolveDid(didString, EXPECT_NO_ERROR); - assert.exists(envelope); - - const msg = envelope.open(); - - assert.exists(msg); - assert.equal(didString, msg.getDid()); - assert.isTrue(msg.isValid()); - assert.equal(DidMethodOperation.DELETE, msg.getOperation()); - assert.notEqual(didDocument, msg.getDidDocument()); - }); - - it('Test Resolve After Delete And Another Invalid Submit', async function() { - this.timeout(60000); - await testBase.sendDidTransaction(hcsDid, didDocument, DidMethodOperation.UPDATE, EXPECT_NO_ERROR); - - const didString = hcsDid.toDid(); - const envelope = await testBase.resolveDid(didString, EXPECT_NO_ERROR); - assert.exists(envelope); - - const msg = envelope.open(); - - assert.exists(msg); - assert.equal(didString, msg.getDid()); - assert.isTrue(msg.isValid()); - assert.equal(DidMethodOperation.DELETE, msg.getOperation()); - assert.notEqual(didDocument, msg.getDidDocument()); - }); -}) diff --git a/test/did/hcs-did-root-key.js b/test/did/hcs-did-root-key.js deleted file mode 100644 index b10c0db..0000000 --- a/test/did/hcs-did-root-key.js +++ /dev/null @@ -1,37 +0,0 @@ -const { - FileId -} = require('@hashgraph/sdk'); -const bs58 = require('bs58'); -const { - HcsDid, - HcsDidRootKey -} = require("../../dist"); - -const {assert} = require('chai'); - -const network = 'network'; - -describe('HcsDidRootKey', function() { - it('Test Generate', async function() { - const addressBook = '0.0.1'; - - const privateKey = HcsDid.generateDidRootKey(); - - const did = new HcsDid(network, privateKey.publicKey, FileId.fromString(addressBook)); - - assert.throw(() => {HcsDidRootKey.fromHcsIdentity(null, null);}); - assert.throw(() => {HcsDidRootKey.fromHcsIdentity(did, null);}); - assert.throw(() => {HcsDidRootKey.fromHcsIdentity(null, privateKey.publicKey);}); - - const differentPublicKey = HcsDid.generateDidRootKey().publicKey; - assert.throw(() => {HcsDidRootKey.fromHcsIdentity(did, differentPublicKey);}); - - const didRootKey = HcsDidRootKey.fromHcsIdentity(did, privateKey.publicKey); - assert.exists(didRootKey); - - assert.equal(didRootKey.getType(), 'Ed25519VerificationKey2018'); - assert.equal(didRootKey.getId(), did.toDid() + HcsDidRootKey.DID_ROOT_KEY_NAME); - assert.equal(didRootKey.getController(), did.toDid()); - assert.equal(didRootKey.getPublicKeyBase58(), bs58.encode(privateKey.publicKey.toBytes())); - }); -}); diff --git a/test/did/hcs-did.js b/test/did/hcs-did.js deleted file mode 100644 index 91f436f..0000000 --- a/test/did/hcs-did.js +++ /dev/null @@ -1,126 +0,0 @@ -const { - FileId, - TopicId -} = require('@hashgraph/sdk'); -const bs58 = require('bs58'); -const { - DidSyntax, - HcsDid -} = require("../../dist"); - -const {assert} = require('chai'); - -const network = 'network'; - -describe('HcsDid', function() { - it('Test Generate And Parse Did Without Tid', async function() { - const addressBook = '0.0.24352'; - - const privKey = HcsDid.generateDidRootKey(); - const pubKey = privKey.publicKey; - - const did = new HcsDid(network, pubKey, FileId.fromString(addressBook)); - - const didString = did.toString(); - - assert.exists(didString); - - const parsedDid = HcsDid.fromString(didString); - - assert.exists(parsedDid); - assert.exists(parsedDid.getAddressBookFileId()); - - assert.notExists(parsedDid.getDidTopicId()); - - assert.equal(parsedDid.toString(), didString); - assert.equal(parsedDid.getMethod(), DidSyntax.Method.HEDERA_HCS); - assert.equal(parsedDid.getNetwork(), network); - assert.equal(parsedDid.getAddressBookFileId().toString(), addressBook); - assert.equal(parsedDid.getIdString(), did.getIdString()); - }); - - it('Test Generate And Parse Did With Tid', async function() { - const addressBook = '0.0.24352'; - const didTopicId = '1.5.23462345'; - - const privateKey = HcsDid.generateDidRootKey(); - - const fileId = FileId.fromString(addressBook); - const topicId = TopicId.fromString(didTopicId); - const did = new HcsDid(network, privateKey.publicKey, fileId, topicId); - - const didString = did.toString(); - - assert.exists(didString); - - const parsedDid = HcsDid.fromString(didString); - - assert.exists(parsedDid); - assert.exists(parsedDid.getAddressBookFileId()); - assert.exists(parsedDid.getDidTopicId()); - - assert.equal(parsedDid.toDid(), didString); - assert.equal(parsedDid.getMethod(), DidSyntax.Method.HEDERA_HCS); - assert.equal(parsedDid.getNetwork(), network); - assert.equal(parsedDid.getAddressBookFileId().toString(), addressBook); - assert.equal(parsedDid.getDidTopicId().toString(), didTopicId); - assert.equal(parsedDid.getIdString(), did.getIdString()); - - const parsedDocument = parsedDid.generateDidDocument(); - - assert.exists(parsedDocument); - assert.equal(parsedDocument.getId(), parsedDid.toString()); - assert.equal(parsedDocument.getContext(), DidSyntax.DID_DOCUMENT_CONTEXT); - assert.notExists(parsedDocument.getDidRootKey()); - - const document = did.generateDidDocument(); - - assert.exists(document); - assert.equal(document.getId(), parsedDid.toString()); - assert.equal(document.getContext(), DidSyntax.DID_DOCUMENT_CONTEXT); - assert.exists(document.getDidRootKey()); - assert.equal(document.getDidRootKey().getPublicKeyBase58(), bs58.encode(privateKey.publicKey.toBytes())); - }); - - it('Test Parse Predefined Dids', async function() { - const addressBook = '0.0.24352'; - const didTopicId = '1.5.23462345'; - - const validDidWithSwitchedParamsOrder = "did:hedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak" - + ";hedera:testnet:tid=" + didTopicId - + ";hedera:testnet:fid=" + addressBook; - - const invalidDids = [ - null, - "invalidDid1", - "did:invalid", - "did:invalidMethod:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;hedera:testnet:fid=0.0.24352", - "did:hedera:invalidNetwork:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;hedera:testnet:fid=0.0.24352", - "did:hedera:testnet:invalidAddress;hedera:testnet:fid=0.0.24352;hedera:testnet:tid=1.5.23462345", - "did:hedera:testnet;hedera:testnet:fid=0.0.24352;hedera:testnet:tid=1.5.23462345", - "did:hedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;missing:fid=0.0.24352;" - + "hedera:testnet:tid=1.5.2", - "did:hedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;missing:fid=0.0.1;" - + "hedera:testnet:tid=1.5.2;unknown:parameter=1", - "did:hedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;hedera:testnet:fid=0.0.1=1", - "did:hedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;hedera:testnet:fid", - "did:hedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:unknownPart;hedera:testnet:fid=0.0.1", - "did:notHedera:testnet:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak;hedera:testnet:fid=0.0.1" - ]; - - for (let did of invalidDids) { - assert.throw(() => { - HcsDid.fromString(did); - }); - } - - const validDid = HcsDid.fromString(validDidWithSwitchedParamsOrder); - - assert.exists(validDid); - assert.exists(validDid.getAddressBookFileId()); - assert.exists(validDid.getDidTopicId()); - - assert.equal(validDid.getAddressBookFileId().toString(), addressBook); - assert.equal(validDid.getDidTopicId().toString(), didTopicId); - }); -}); diff --git a/test/hcs-identity-network.js b/test/hcs-identity-network.js deleted file mode 100644 index 93c94c0..0000000 --- a/test/hcs-identity-network.js +++ /dev/null @@ -1,168 +0,0 @@ -const {OPERATOR_KEY, OPERATOR_ID, NETWORK} = require("./variables"); -const { - AccountId, - PrivateKey, - Client, - FileCreateTransaction, - Hbar, - TopicInfoQuery -} = require('@hashgraph/sdk'); - -const { - AddressBook, - HcsDid, - HcsIdentityNetworkBuilder, - HcsIdentityNetwork -} = require("../dist"); - -const {assert} = require('chai'); - -const FEE = new Hbar(2); -const ADDRESS_BOOK_JSON = "{\"appnetName\":\"Test Identity SDK appnet\",\"didTopicId\":\"0.0.214919\",\"vcTopicId\":\"0.0.214920\",\"appnetDidServers\":[\"http://localhost:3000/api/v1\"]}"; - -let client, - operatorId, - operatorKey, - addressBookFileId, - network; - -describe('HcsIdentityNetwork', function() { - before(async function() { - this.timeout(60000); - - operatorId = AccountId.fromString(OPERATOR_ID); - operatorKey = PrivateKey.fromString(OPERATOR_KEY); - network = NETWORK; - client = Client.forTestnet(); - client.setMirrorNetwork(["hcs." + network + ".mirrornode.hedera.com:5600"]); - client.setOperator(operatorId, operatorKey); - - const response = await new FileCreateTransaction() - .setContents(ADDRESS_BOOK_JSON) - .setKeys([operatorKey.publicKey]) - .setMaxTransactionFee(FEE) - .execute(client); - - const receipt = await response.getReceipt(client); - addressBookFileId = receipt.fileId; - }); - - it('Test Create Identity Network', async function() { - this.timeout(60000); - const appnetName = 'Test Identity SDK appnet'; - const didServerUrl = 'http://localhost:3000/api/v1'; - const didTopicMemo = 'Test Identity SDK appnet DID topic'; - const vcTopicMemo = 'Test Identity SDK appnet VC topic'; - - const didNetwork = await new HcsIdentityNetworkBuilder() - .setNetwork(network) - .setAppnetName(appnetName) - .addAppnetDidServer(didServerUrl) - .setPublicKey(operatorKey.publicKey) - .setMaxTransactionFee(FEE) - .setDidTopicMemo(didTopicMemo) - .setVCTopicMemo(vcTopicMemo) - .execute(client); - - assert.exists(didNetwork); - assert.exists(didNetwork.getAddressBook()); - - const addressBook = didNetwork.getAddressBook(); - assert.exists(addressBook.getDidTopicId()); - assert.exists(addressBook.getVcTopicId()); - assert.exists(addressBook.getAppnetDidServers()); - assert.exists(addressBook.getFileId()); - assert.equal(addressBook.getAppnetName(), appnetName); - assert.equal(didNetwork.getNetwork(), network); - - const didTopicInfo = await new TopicInfoQuery() - .setTopicId(didNetwork.getDidTopicId()) - .execute(client); - - assert.exists(didTopicInfo); - assert.equal(didTopicInfo.topicMemo, didTopicMemo); - - const vcTopicInfo = await new TopicInfoQuery() - .setTopicId(didNetwork.getVcTopicId()) - .execute(client); - - assert.exists(vcTopicInfo); - assert.equal(vcTopicInfo.topicMemo, vcTopicMemo); - - const createdNetwork = await HcsIdentityNetwork.fromAddressBookFile(client, network, addressBook.getFileId()); - assert.exists(createdNetwork); - assert.equal(addressBook.toJSON(), createdNetwork.getAddressBook().toJSON()); - }); - - it('Test Init Network From Json AddressBook', async function() { - this.timeout(60000); - const addressBook = AddressBook.fromJson(ADDRESS_BOOK_JSON, addressBookFileId); - const didNetwork = HcsIdentityNetwork.fromAddressBook(network, addressBook); - - assert.exists(didNetwork); - assert.exists(didNetwork.getAddressBook().getFileId()); - assert.equal(didNetwork.getNetwork(), network); - }); - - it('Test Init Network From Did', async function() { - this.timeout(60000); - const did = new HcsDid(network, HcsDid.generateDidRootKey().publicKey, addressBookFileId); - - const didNetwork = await HcsIdentityNetwork.fromHcsDid(client, did); - - assert.exists(didNetwork); - assert.exists(didNetwork.getAddressBook().getFileId()); - assert.equal(didNetwork.getNetwork(), network); - assert.equal(ADDRESS_BOOK_JSON, didNetwork.getAddressBook().toJSON()); - }); - - it('Test Generate Did For Network', async function() { - this.timeout(60000); - - function checkTestGenerateDidForNetwork(did, publicKey, didTopicId, withTid) { - assert.exists(did); - assert.equal(HcsDid.publicKeyToIdString(publicKey), did.getIdString()); - assert.equal(did.getNetwork(), network); - assert.equal(did.getAddressBookFileId(), addressBookFileId); - if (withTid) { - assert.equal(did.getDidTopicId().toString(), didTopicId) - } else { - assert.notExists(did.getDidTopicId()); - } - assert.equal(did.getMethod(), HcsDid.DID_METHOD); - } - - const addressBook = AddressBook.fromJson(ADDRESS_BOOK_JSON, addressBookFileId); - const didNetwork = HcsIdentityNetwork.fromAddressBook(network, addressBook); - - let did = didNetwork.generateDid(true); - assert.exists(did.getPrivateDidRootKey()); - - let publicKey = did.getPrivateDidRootKey().publicKey; - checkTestGenerateDidForNetwork(did, publicKey, addressBook.getDidTopicId(), true); - - did = didNetwork.generateDid(false); - assert.exists(did.getPrivateDidRootKey()); - - publicKey = did.getPrivateDidRootKey().publicKey; - checkTestGenerateDidForNetwork(did, publicKey, addressBook.getDidTopicId(), false); - - did = didNetwork.generateDid(true); - assert.exists(did.getPrivateDidRootKey()); - publicKey = did.getPrivateDidRootKey().publicKey; - checkTestGenerateDidForNetwork(did, publicKey, addressBook.getDidTopicId(), true); - - did = didNetwork.generateDid(false); - assert.exists(did.getPrivateDidRootKey()); - publicKey = did.getPrivateDidRootKey().publicKey; - checkTestGenerateDidForNetwork(did, publicKey, addressBook.getDidTopicId(), false); - - publicKey = HcsDid.generateDidRootKey().publicKey; - did = didNetwork.generateDid(publicKey, true); - checkTestGenerateDidForNetwork(did, publicKey, addressBook.getDidTopicId(), true); - - publicKey = HcsDid.generateDidRootKey().publicKey; - did = didNetwork.generateDid(publicKey, false); - checkTestGenerateDidForNetwork(did, publicKey, addressBook.getDidTopicId(), false); - }); -}); diff --git a/test/integration/did-resolver.test.ts b/test/integration/did-resolver.test.ts new file mode 100644 index 0000000..3108da0 --- /dev/null +++ b/test/integration/did-resolver.test.ts @@ -0,0 +1,157 @@ +import { AccountId, Client, PrivateKey } from "@hashgraph/sdk"; +import { Resolver } from "did-resolver"; +import { Hashing, HcsDid, HederaDidResolver } from "../../dist"; +import { delayUntil } from "../utils"; + +const OPERATOR_ID = process.env.OPERATOR_ID; +const OPERATOR_KEY = process.env.OPERATOR_KEY; + +const WAIT_BEFORE_RESOLVE_DID_FOR = parseInt(process.env.WAIT_BEFORE_RESOLVE_DID_FOR); + +describe("HederaDidResolver", () => { + let client; + + beforeEach(async () => { + const operatorId = AccountId.fromString(OPERATOR_ID); + const operatorKey = PrivateKey.fromString(OPERATOR_KEY); + client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(operatorId, operatorKey); + }); + + afterEach(() => { + client.close(); + }); + + describe("#resolve", () => { + it("returns error response", async () => { + const resolver = new Resolver({ + ...new HederaDidResolver(client).build(), + }); + + let result = await resolver.resolve("did:hedera:testnet:nNCTE5bZdRmjm2obqJwS892jVLak_0.0.1"); + expect(result).toEqual({ + didDocument: null, + didDocumentMetadata: {}, + didResolutionMetadata: { + error: "invalidDid", + message: "Error: DID string is invalid. ID holds incorrect format.", + }, + }); + + /** + * Does not return messages because Resolver wrapper handles that + */ + result = await resolver.resolve(""); + expect(result).toEqual({ + didDocument: null, + didDocumentMetadata: {}, + didResolutionMetadata: { + error: "invalidDid", + }, + }); + + result = await resolver.resolve( + "did:hedera:invalidNetwork:nNCTE5bZdRmjm2obqJwS892jVLakafasdfasdfasffwvdasdfasqqwe_0.0.1" + ); + expect(result).toEqual({ + didDocument: null, + didDocumentMetadata: {}, + didResolutionMetadata: { + error: "unknownNetwork", + message: "Error: DID string is invalid. Invalid Hedera network.", + }, + }); + }); + + it("returns success response", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + await did.addService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + + const resolver = new Resolver({ + ...new HederaDidResolver().build(), + }); + + let result: any; + + await delayUntil(async () => { + result = await resolver.resolve(did.getIdentifier()); + return result?.didDocument?.service?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(result).toEqual({ + didDocument: { + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + service: [ + { + id: `${did.getIdentifier()}#service-1`, + serviceEndpoint: "https://example.com/vcs", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }, + didDocumentMetadata: { + created: expect.anything(), + updated: expect.anything(), + versionId: expect.anything(), + }, + didResolutionMetadata: { + contentType: "application/did+ld+json", + }, + }); + }); + + it("returns deactivated did document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + await did.delete(); + + const resolver = new Resolver({ + ...new HederaDidResolver().build(), + }); + + let result: any; + + await delayUntil(async () => { + result = await resolver.resolve(did.getIdentifier()); + return result?.didDocument?.verificationMethod?.length === 0; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(result).toEqual({ + didDocument: { + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [], + authentication: [], + id: did.getIdentifier(), + verificationMethod: [], + }, + didDocumentMetadata: { + versionId: null, + deactivated: true, + }, + didResolutionMetadata: { + contentType: "application/did+ld+json", + }, + }); + }); + }); +}); diff --git a/test/integration/hcs-did.test.ts b/test/integration/hcs-did.test.ts new file mode 100644 index 0000000..4676545 --- /dev/null +++ b/test/integration/hcs-did.test.ts @@ -0,0 +1,1107 @@ +import { AccountId, Client, PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDid } from "../../dist"; +import { delayUntil, readTopicMessages } from "../utils"; + +const TOPIC_REGEXP = /^0\.0\.[0-9]{3,}/; + +const OPERATOR_ID = process.env.OPERATOR_ID; +const OPERATOR_KEY = process.env.OPERATOR_KEY; + +const WAIT_BEFORE_RESOLVE_DID_FOR = parseInt(process.env.WAIT_BEFORE_RESOLVE_DID_FOR); + +describe("HcsDid", () => { + let client; + + beforeEach(async () => { + const operatorId = AccountId.fromString(OPERATOR_ID); + const operatorKey = PrivateKey.fromString(OPERATOR_KEY); + client = Client.forTestnet({ scheduleNetworkUpdate: false }); + client.setOperator(operatorId, operatorKey); + }); + + afterEach(() => { + client.close(); + }); + + describe("#register", () => { + it("throws error if DID is already registered", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + + await delayUntil(async () => { + const didDoc = await did.resolve(); + const didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + let error; + try { + await did.register(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID is already registered"); + }); + + it("throws error if client configuration is missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey }); + + let error; + try { + await did.register(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("creates new DID by registering a topic and submitting first message", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + const result = await did.register(); + + expect(result).toEqual(did); + + expect(did.getTopicId().toString()).toMatch(TOPIC_REGEXP); + expect(did.getIdentifier()).toEqual( + `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_${did + .getTopicId() + .toString()}` + ); + expect(did.getPrivateKey()).toEqual(privateKey); + expect(did.getClient()).toEqual(client); + expect(did.getNetwork()).toEqual("testnet"); + + await delayUntil(async () => { + const didDoc = await did.resolve(); + const didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + const messages = await readTopicMessages(did.getTopicId(), client); + + expect(messages.length).toEqual(1); + }); + + it("deletes DID document and registers it again without creating a new topic", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + const topicId = did.getTopicId(); + + await delayUntil(async () => { + const didDoc = await did.resolve(); + const didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + let messages = await readTopicMessages(did.getTopicId(), client); + expect(messages.length).toEqual(1); + + await did.delete(); + expect(did.getTopicId()).toEqual(topicId); + + await delayUntil(async () => { + const didDoc = await did.resolve(); + const didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 0; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + messages = await readTopicMessages(did.getTopicId(), client); + expect(messages.length).toEqual(2); + + await did.register(); + expect(did.getTopicId()).toEqual(topicId); + + await delayUntil(async () => { + const didDoc = await did.resolve(); + const didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + messages = await readTopicMessages(did.getTopicId(), client); + expect(messages.length).toEqual(3); + }); + }); + + describe("#resolve", () => { + it("throws error about unregistered DID", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey, client }); + + let error; + try { + await did.resolve(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID is not registered"); + }); + + it("throws error about missing Client parameter", async () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier }); + + let error; + try { + await did.resolve(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("successfully resolves just registered DID", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length > 0; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + }); + }); + + describe("#delete", () => { + it("throws error if DID is not registered", async () => { + const did = new HcsDid({ privateKey: PrivateKey.fromString(OPERATOR_KEY), client }); + let error; + try { + await did.delete(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID is not registered"); + }); + + it("throws error if instance has no privateKey assigned", async () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier, client }); + let error; + try { + await did.delete(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("privateKey is missing"); + }); + + it("throws error if instance has no client assigned", async () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier, privateKey: PrivateKey.fromString(OPERATOR_KEY) }); + let error; + try { + await did.delete(); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("deletes the DID document", async () => { + const didPrivateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey: didPrivateKey, client }); + + await did.register(); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(didPrivateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + await did.delete(); + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 0; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [], + authentication: [], + id: did.getIdentifier(), + verificationMethod: [], + }); + + const messages = await readTopicMessages(did.getTopicId(), client); + expect(messages.length).toEqual(2); + }); + }); + + describe("#changeOwner", () => { + const docIdentifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.99999999"; + const newOwnerIdentifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + + it("throws error that DID is not registered", async () => { + const didPrivateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey: didPrivateKey, client: client }); + + let error; + try { + await did.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: PrivateKey.generate(), + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID is not registered"); + }); + + it("throws error that privateKey is missing", async () => { + const did = new HcsDid({ + identifier: docIdentifier, + client: client, + }); + + let error; + try { + await did.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: PrivateKey.generate(), + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("privateKey is missing"); + }); + + it("throws error that Client configuration is missing", async () => { + const didPrivateKey = PrivateKey.generate(); + const did = new HcsDid({ + identifier: docIdentifier, + privateKey: didPrivateKey, + }); + + let error; + try { + await did.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: PrivateKey.generate(), + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("throws error that newPrivateKey is missing", async () => { + const didPrivateKey = PrivateKey.generate(); + const did = new HcsDid({ + identifier: docIdentifier, + privateKey: didPrivateKey, + client: client, + }); + + let error; + try { + await did.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: null, + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("newPrivateKey is missing"); + }); + + it("changes the owner of the document", async () => { + const didPrivateKey = PrivateKey.generate(); + const newDidPrivateKey = PrivateKey.generate(); + const did = new HcsDid({ + privateKey: didPrivateKey, + client: client, + }); + + await did.register(); + + await did.changeOwner({ + controller: newOwnerIdentifier, + newPrivateKey: newDidPrivateKey, + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.controller === newOwnerIdentifier; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + controller: newOwnerIdentifier, + id: did.getIdentifier(), + verificationMethod: [ + { + controller: newOwnerIdentifier, + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(newDidPrivateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + const messages = await readTopicMessages(did.getTopicId(), client); + expect(messages.length).toEqual(2); + }); + }); + + describe("Add Update and Revoke Service meta-information", () => { + it("throws error if privatekey is missing", async () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier }); + + let error; + try { + await did.addService({ id: null, type: null, serviceEndpoint: null }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("privateKey is missing"); + }); + + it("throws error if client configuration is missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey }); + + let error; + try { + await did.addService({ id: null, type: null, serviceEndpoint: null }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("throws error if Service arguments are missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey, client }); + + let error; + try { + await did.addService({ id: null, type: null, serviceEndpoint: null }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if event id is not valid", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + let error; + try { + await did.register(); + await did.addService({ + id: did.getIdentifier() + "#invalid-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#service-{integer}"); + }); + + it("publish a new Service message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + await did.addService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.service?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + service: [ + { + id: `${did.getIdentifier()}#service-1`, + serviceEndpoint: "https://example.com/vcs", + type: "LinkedDomains", + }, + ], + }); + + // DIDOwner and Service event + expect(did.getMessages().length).toEqual(2); + }); + + it("publish an update Service message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + await did.addService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + await did.updateService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/did", + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.service[0]?.serviceEndpoint === "https://example.com/did"; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + service: [ + { + id: `${did.getIdentifier()}#service-1`, + serviceEndpoint: "https://example.com/did", + type: "LinkedDomains", + }, + ], + }); + + expect(did.getMessages().length).toEqual(3); + }); + + it("publish a revoke Service message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + await did.addService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + await did.revokeService({ + id: did.getIdentifier() + "#service-1", + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod === 1 && !didDocument?.service; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + expect(did.getMessages().length).toEqual(3); + }); + + it("revoke and re-add Service with same service-ID and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + await did.register(); + await did.addService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://example.com/vcs", + }); + await did.revokeService({ + id: did.getIdentifier() + "#service-1", + }); + + await did.addService({ + id: did.getIdentifier() + "#service-1", + type: "LinkedDomains", + serviceEndpoint: "https://meeco.me/vijay", + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.service?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + service: [ + { + id: `${did.getIdentifier()}#service-1`, + serviceEndpoint: "https://meeco.me/vijay", + type: "LinkedDomains", + }, + ], + }); + + expect(did.getMessages().length).toEqual(4); + }); + }); + + describe("Add Update and Revoke VerificationMethod meta-information", () => { + it("throws error if privatekey is missing", async () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier }); + + let error; + try { + await did.addVerificationMethod({ id: null, type: null, controller: null, publicKey: null }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("privateKey is missing"); + }); + + it("throws error if client configuration is missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey }); + + let error; + try { + await did.addVerificationMethod({ id: null, type: null, controller: null, publicKey: null }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("throws error if Verification Method arguments are missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey, client }); + + let error; + try { + await did.addVerificationMethod({ id: null, type: null, controller: null, publicKey: null }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("publish a new VerificationMethod message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + //new verification DID and publickey + const newVerificationDid = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801#key-1"; + const publicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + + await did.register(); + await did.addVerificationMethod({ + id: newVerificationDid, + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey, + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 2; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`${did.getIdentifier()}`); + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: did.getIdentifier(), + id: newVerificationDid, + publicKeyBase58: Hashing.base58.encode(publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + // DIDOwner and VerificationMethod event + expect(did.getMessages().length).toEqual(2); + }); + + it("publish an update VerificationMethod message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + //new verification DID and publickey + const newVerificationDid = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801#key-1"; + const publicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + const updatePublicKey = HcsDid.stringToPublicKey("zAvU2AEh8ybRqNwHAM3CjbkjYaYHpt9oA1uugW9EVTg6P"); + + await did.register(); + await did.addVerificationMethod({ + id: newVerificationDid, + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey, + }); + await did.updateVerificationMethod({ + id: newVerificationDid, + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey: updatePublicKey, + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return ( + didDocument?.verificationMethod[1]?.publicKeyBase58 === + Hashing.base58.encode(updatePublicKey.toBytes()) + ); + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`${did.getIdentifier()}`); + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: did.getIdentifier(), + id: newVerificationDid, + publicKeyBase58: Hashing.base58.encode(updatePublicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + // DIDOwner and VerificationMethod event + expect(did.getMessages().length).toEqual(3); + }); + it("publish a revoke VerificationMethod message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + //new verification DID and publickey + const newVerificationDid = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801#key-1"; + const publicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + + await did.register(); + await did.addVerificationMethod({ + id: newVerificationDid, + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey, + }); + await did.revokeVerificationMethod({ + id: newVerificationDid, + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.verificationMethod?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + console.log(`${did.getIdentifier()}`); + console.log(`https://testnet.dragonglass.me/hedera/topics/${did.getTopicId().toString()}`); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + // DIDOwner and VerificationMethod event + expect(did.getMessages().length).toEqual(3); + }); + }); + + describe("Add Update and Revoke VerificationMethod Relationship meta-information", () => { + it("throws error if privatekey is missing", async () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier }); + + let error; + try { + await did.addVerificationRelationship({ + id: null, + relationshipType: null, + type: null, + controller: null, + publicKey: null, + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("privateKey is missing"); + }); + + it("throws error if client configuration is missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey }); + + let error; + try { + await did.addVerificationRelationship({ + id: null, + relationshipType: null, + type: null, + controller: null, + publicKey: null, + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Client configuration is missing"); + }); + + it("throws error if Verification Relationship arguments are missing", async () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey, client }); + + let error; + try { + await did.addVerificationRelationship({ + id: null, + relationshipType: null, + type: null, + controller: null, + publicKey: null, + }); + } catch (err) { + error = err; + } + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("publish a new VerificationRelationship message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + //new verification DID and publickey + const newVerificationDid = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801#key-1"; + const publicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + + await ( + await did.register() + ).addVerificationRelationship({ + id: newVerificationDid, + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey, + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.authentication?.length === 2; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`, `${newVerificationDid}`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: did.getIdentifier(), + id: newVerificationDid, + publicKeyBase58: Hashing.base58.encode(publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + // DIDOwner and VerificationMethod event + expect(did.getMessages().length).toEqual(2); + }); + + it("publish an update VerificationRelationship message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + const pk = PrivateKey.generate(); + console.log(Hashing.multibase.encode(pk.publicKey.toBytes())); + + // new verification DID and publickey + const newVerificationDid = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801#key-1"; + + const publicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + const updatePublicKey = HcsDid.stringToPublicKey("zAvU2AEh8ybRqNwHAM3CjbkjYaYHpt9oA1uugW9EVTg6P"); + + await did.register(); + await did.addVerificationRelationship({ + id: newVerificationDid, + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey, + }); + await did.updateVerificationRelationship({ + id: newVerificationDid, + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey: updatePublicKey, + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return ( + didDocument?.verificationMethod[1]?.publicKeyBase58 === + Hashing.base58.encode(updatePublicKey.toBytes()) + ); + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`, `${newVerificationDid}`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: did.getIdentifier(), + id: newVerificationDid, + publicKeyBase58: Hashing.base58.encode(updatePublicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + // DIDOwner and VerificationMethod event + expect(did.getMessages().length).toEqual(3); + }); + + it("publish a revoke VerificationRelationship message and verify DID Document", async () => { + const privateKey = PrivateKey.fromString(OPERATOR_KEY); + const did = new HcsDid({ privateKey, client }); + + //new verification DID and publickey + const newVerificationDid = + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29617801#key-1"; + const publicKey = HcsDid.stringToPublicKey("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + + await did.register(); + await did.addVerificationRelationship({ + id: newVerificationDid, + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + controller: did.getIdentifier(), + publicKey, + }); + await did.revokeVerificationRelationship({ + id: newVerificationDid, + relationshipType: "authentication", + }); + + let didDocument: any; + + await delayUntil(async () => { + const didDoc = await did.resolve(); + didDocument = didDoc.toJsonTree(); + return didDocument?.authentication?.length === 1; + }, WAIT_BEFORE_RESOLVE_DID_FOR); + + expect(didDocument).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${did.getIdentifier()}#did-root-key`], + authentication: [`${did.getIdentifier()}#did-root-key`], + id: did.getIdentifier(), + verificationMethod: [ + { + controller: did.getIdentifier(), + id: `${did.getIdentifier()}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + + // DIDOwner and VerificationMethod event + expect(did.getMessages().length).toEqual(3); + }); + }); +}); + +/** + * Test Helpers + */ diff --git a/test/network-ready-test-base.js b/test/network-ready-test-base.js deleted file mode 100644 index d17ef93..0000000 --- a/test/network-ready-test-base.js +++ /dev/null @@ -1,222 +0,0 @@ -const {OPERATOR_KEY, OPERATOR_ID, NETWORK} = require("./variables"); -const { - AccountId, - PrivateKey, - Client, - FileId, - Hbar -} = require('@hashgraph/sdk'); - -const { - AddressBook, - HcsIdentityNetworkBuilder, - HcsIdentityNetwork -} = require("../dist"); - -const MIRROR_NODE_TIMEOUT = 30 * 1000; -const NO_MORE_MESSAGES_TIMEOUT = 15 * 1000; -const FEE = new Hbar(2); - -const EXISTING_ADDRESS_BOOK_FILE_ID = null; -const EXISTING_ADDRESS_BOOK_JSON = null; - -const sleep = function (sleepTime) { - return new Promise(resolve => { - setTimeout(() => { - resolve(); - }, sleepTime) - }) -} - -const until = function (maxTime, untilFunction) { - return new Promise((resolve, reject) => { - let t, i; - i = setInterval(() => { - if (untilFunction()) { - clearInterval(i); - clearTimeout(t); - resolve(); - } - }, 100); - t = setTimeout(() => { - clearInterval(i); - clearTimeout(t); - resolve(); - }, maxTime) - }) -} - - -/** - * Base class for test classes that need a hedera identity network set up before running. - */ -class NetworkReadyTestBase { - operatorId; - operatorKey; - network; - didNetwork; - client; - - /** - * Initialize hedera clients and accounts. - */ - // BeforeAll - async setup() { - this.operatorId = AccountId.fromString(OPERATOR_ID); - this.operatorKey = PrivateKey.fromString(OPERATOR_KEY); - this.network = NETWORK; - - // Build Hedera testnet client - switch (this.network.toUpperCase()) { - case "MAINNET": - this.client = Client.forMainnet(); - break; - case "TESTNET": - this.client = Client.forTestnet(); - break; - case "PREVIEWNET": - this.client = Client.forPreviewnet(); - break; - default: - throw "Illegal argument for network."; - } - - // Set the operator account ID and operator private key - this.client.setOperator(this.operatorId, this.operatorKey); - - // If identity network is provided as environment variable read from there, otherwise setup new one: - const abJson = EXISTING_ADDRESS_BOOK_JSON; - const abFileId = EXISTING_ADDRESS_BOOK_FILE_ID; - if (!(abJson) || !(abFileId)) { - await this.setupIdentityNetwork(); - } else { - const addressBook = AddressBook.fromJson(abJson, FileId.fromString(abFileId)); - this.didNetwork = HcsIdentityNetwork.fromAddressBook(this.network, addressBook); - } - } - - async setupIdentityNetwork() { - const appnetName = "Test Identity SDK appnet"; - const didServerUrl = "http://localhost:3000/api/v1"; - const didTopicMemo = "Test Identity SDK appnet DID topic"; - const vcTopicMemo = "Test Identity SDK appnet VC topic"; - - this.didNetwork = await new HcsIdentityNetworkBuilder() - .setNetwork(this.network) - .setAppnetName(appnetName) - .addAppnetDidServer(didServerUrl) - .setPublicKey(this.operatorKey.publicKey) - .setMaxTransactionFee(FEE) - .setDidTopicMemo(didTopicMemo) - .setVCTopicMemo(vcTopicMemo) - .execute(this.client); - console.info("New identity network created: " + appnetName); - console.info("Sleeping 10s to allow propagation of new topics to mirror node"); - - await sleep(10000); - } - - //AfterAll - cleanup() { - try { - if (this.client != null) { - this.client.close(); - } - - if (this.client != null) { - this.client.close(); - } - } catch (e) { - // ignore - } - } - - async sendDidTransaction(did, didDocumentJson, operation, onError) { - const messageRef = []; - - // Build and execute transaction - await this.didNetwork.createDidTransaction(operation) - .setDidDocument(didDocumentJson) - .signMessage(doc => did.getPrivateDidRootKey().sign(doc)) - .buildAndSignTransaction(tx => tx.setMaxTransactionFee(FEE)) - .onMessageConfirmed(msg => messageRef.push(msg)) - .onError(onError) - .execute(this.client); - - // Wait until consensus is reached and mirror node received the DID document, but with max. time limit. - await until(MIRROR_NODE_TIMEOUT, () => !!messageRef.length); - - try { - return messageRef[0]; - } catch (error) { - return undefined - } - } - - async resolveDid(didString, onError) { - const mapRef = []; - - // Now resolve the DID. - this.didNetwork.getDidResolver() - .addDid(didString) - .setTimeout(NO_MORE_MESSAGES_TIMEOUT) - .onError(onError) - .whenFinished(m => mapRef.push(m)) - .execute(this.client); - - // Wait until mirror node resolves the DID. - await until(MIRROR_NODE_TIMEOUT, () => !!mapRef.length); - - try { - return mapRef[0].get(didString); - } catch (error) { - return undefined - } - } - - async sendVcTransaction(operation, credentialHash, signingKey, onError) { - const messageRef = []; - - // Build and execute transaction - await this.didNetwork.createVcTransaction(operation, credentialHash, signingKey.publicKey) - .signMessage(doc => signingKey.sign(doc)) - .buildAndSignTransaction(tx => tx.setMaxTransactionFee(FEE)) - .onMessageConfirmed(msg => messageRef.push(msg)) - .onError(onError) - .execute(this.client); - - // Wait until consensus is reached and mirror node received the DID document, but with max. time limit. - await until(MIRROR_NODE_TIMEOUT, () => !!messageRef.length); - - try { - return messageRef[0]; - } catch (error) { - return undefined - } - } - - async resolveVcStatus(credentialHash, provider, onError) { - const mapRef = []; - - // Now resolve the DID. - this.didNetwork.getVcStatusResolver(provider) - .addCredentialHash(credentialHash) - .setTimeout(NO_MORE_MESSAGES_TIMEOUT) - .onError(onError) - .whenFinished(m => mapRef.push(m)) - .execute(this.client); - - // Wait until mirror node resolves the DID. - await until(MIRROR_NODE_TIMEOUT, () => !!mapRef.length); - - try { - return mapRef[0].get(credentialHash); - } catch (error) { - return undefined - } - } -} - -exports.NetworkReadyTestBase = NetworkReadyTestBase; -exports.until = until; -exports.sleep = sleep; diff --git a/test/unit/did-document.test.ts b/test/unit/did-document.test.ts new file mode 100644 index 0000000..8d6065d --- /dev/null +++ b/test/unit/did-document.test.ts @@ -0,0 +1,640 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { + DidDocument, + DidMethodOperation, + Hashing, + HcsDidCreateDidDocumentEvent, + HcsDidCreateDidOwnerEvent, + HcsDidCreateServiceEvent, + HcsDidCreateVerificationMethodEvent, + HcsDidCreateVerificationRelationshipEvent, + HcsDidDeleteEvent, + HcsDidMessage, + HcsDidUpdateDidOwnerEvent, +} from "../../dist"; + +describe("DidDocument", () => { + describe("#toJsonTree", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode( + privateKey.publicKey.toBytes() + )}_0.0.29613327`; + + it("returns empty document if not events were passed", async () => { + const doc = new DidDocument(identifier); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [], + authentication: [], + id: identifier, + verificationMethod: [], + }); + expect(doc.getCreated()).toBeNull(); + expect(doc.getUpdated()).toBeNull(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeNull(); + }); + + it("ignores events til first create DIDOwner event", async () => { + const doc = new DidDocument(identifier); + await doc.processMessages([ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-1", + "LinkedDomains", + "https://test.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-2", + "LinkedDomains", + "https://test2.identity.com" + ) + ), + ]); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + id: identifier, + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`], + service: [ + { + id: `${identifier}#service-2`, + serviceEndpoint: "https://test2.identity.com", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + ], + }); + expect(doc.getCreated()).toBeTruthy(); + expect(doc.getUpdated()).toBeTruthy(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeTruthy(); + }); + + it("handles HcsDidCreateDidDocumentEvent events", async () => { + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidDocumentEvent(`${identifier}#did-document`, "Qm123456") + ), + ]; + + const doc = new DidDocument(identifier); + const documents = { + Qm123456: { + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`], + id: identifier, + service: [ + { + id: `${identifier}#service-1`, + serviceEndpoint: "https://example.com/vcs", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyMultibase: Hashing.multibase.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }, + }; + + doc.setIpfsDownloader({ + downloadDocument: (event: HcsDidCreateDidDocumentEvent) => documents[event.getCid()], + } as any); + + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`], + id: identifier, + service: [ + { + id: `${identifier}#service-1`, + serviceEndpoint: "https://example.com/vcs", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyMultibase: Hashing.multibase.encode(privateKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + }); + + it("handles create DIDOwner event", async () => { + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + ]; + const doc = new DidDocument(identifier); + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`], + id: identifier, + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + ], + }); + expect(doc.getCreated()).toBeTruthy(); + expect(doc.getUpdated()).toBeTruthy(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeTruthy(); + }); + + it("handles DID delete event", async () => { + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + new HcsDidMessage(DidMethodOperation.DELETE, identifier, new HcsDidDeleteEvent()), + ]; + const doc = new DidDocument(identifier); + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [], + authentication: [], + id: identifier, + verificationMethod: [], + }); + expect(doc.getCreated()).toBeNull(); + expect(doc.getUpdated()).toBeNull(); + expect(doc.getDeactivated()).toEqual(true); + expect(doc.getVersionId()).toBeNull(); + }); + + it("handles change DID owner event", async () => { + const otherOwnerKey = PrivateKey.generate(); + const otherOwnerIdentifier = + "did:hedera:testnet:" + Hashing.multibase.encode(otherOwnerKey.publicKey.toBytes()) + "_0.0.29999999"; + const key2 = PrivateKey.generate(); + + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-2", + "capabilityDelegation", + "Ed25519VerificationKey2018", + identifier, + key2.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.UPDATE, + identifier, + new HcsDidUpdateDidOwnerEvent( + otherOwnerIdentifier + "#did-root-key", + otherOwnerIdentifier, + otherOwnerKey.publicKey + ) + ), + ]; + const doc = new DidDocument(identifier); + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${otherOwnerIdentifier}#did-root-key`], + authentication: [`${otherOwnerIdentifier}#did-root-key`], + capabilityDelegation: [`${identifier}#key-2`], + controller: otherOwnerIdentifier, + id: identifier, + verificationMethod: [ + { + controller: otherOwnerIdentifier, + id: `${otherOwnerIdentifier}#did-root-key`, + publicKeyBase58: Hashing.base58.encode(otherOwnerKey.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-2`, + publicKeyBase58: Hashing.base58.encode(key2.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + expect(doc.getCreated()).toBeTruthy(); + expect(doc.getUpdated()).toBeTruthy(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeTruthy(); + }); + + it("successfully handles add service, verificationMethod and verificationRelationship events", async () => { + const key1 = PrivateKey.generate(); + const key2 = PrivateKey.generate(); + + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-1", + "LinkedDomains", + "https://test.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + key1.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-2", + "capabilityDelegation", + "Ed25519VerificationKey2018", + identifier, + key2.publicKey + ) + ), + ]; + const doc = new DidDocument(identifier); + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`], + capabilityDelegation: [`${identifier}#key-2`], + id: identifier, + service: [ + { + id: `${identifier}#service-1`, + serviceEndpoint: "https://test.identity.com", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-1`, + publicKeyBase58: Hashing.base58.encode(key1.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-2`, + publicKeyBase58: Hashing.base58.encode(key2.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + expect(doc.getCreated()).toBeTruthy(); + expect(doc.getUpdated()).toBeTruthy(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeTruthy(); + }); + + it("successfully handles update service, verificationMethod and verificationRelationship events", async () => { + const key1 = PrivateKey.generate(); + const key2 = PrivateKey.generate(); + const key3 = PrivateKey.generate(); + + const key4 = PrivateKey.generate(); + const key5 = PrivateKey.generate(); + + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-1", + "LinkedDomains", + "https://test.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-2", + "LinkedDomains", + "https://test2.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + key1.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-2", + "capabilityDelegation", + "Ed25519VerificationKey2018", + identifier, + key2.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-3", + "authentication", + "Ed25519VerificationKey2018", + identifier, + key3.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.UPDATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-1", + "LinkedDomains", + "https://new.test.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.UPDATE, + identifier, + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + key4.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.UPDATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-2", + "capabilityDelegation", + "Ed25519VerificationKey2018", + identifier, + key5.publicKey + ) + ), + ]; + const doc = new DidDocument(identifier); + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`, `${identifier}#key-3`], + capabilityDelegation: [`${identifier}#key-2`], + id: identifier, + service: [ + { + id: `${identifier}#service-1`, + serviceEndpoint: "https://new.test.identity.com", + type: "LinkedDomains", + }, + { + id: `${identifier}#service-2`, + serviceEndpoint: "https://test2.identity.com", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-1`, + publicKeyBase58: Hashing.base58.encode(key4.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-2`, + publicKeyBase58: Hashing.base58.encode(key5.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-3`, + publicKeyBase58: Hashing.base58.encode(key3.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + expect(doc.getCreated()).toBeTruthy(); + expect(doc.getUpdated()).toBeTruthy(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeTruthy(); + }); + + it("successfully handles revoke service, verificationMethod and verificationRelationship events", async () => { + const key1 = PrivateKey.generate(); + const key2 = PrivateKey.generate(); + const key3 = PrivateKey.generate(); + + const messages = [ + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-1", + "LinkedDomains", + "https://test.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-2", + "LinkedDomains", + "https://test2.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + key1.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-2", + "capabilityDelegation", + "Ed25519VerificationKey2018", + identifier, + key2.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.CREATE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-3", + "authentication", + "Ed25519VerificationKey2018", + identifier, + key3.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.REVOKE, + identifier, + new HcsDidCreateServiceEvent( + identifier + "#service-1", + "LinkedDomains", + "https://test.identity.com" + ) + ), + new HcsDidMessage( + DidMethodOperation.REVOKE, + identifier, + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + key1.publicKey + ) + ), + new HcsDidMessage( + DidMethodOperation.REVOKE, + identifier, + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-2", + "capabilityDelegation", + "Ed25519VerificationKey2018", + identifier, + key2.publicKey + ) + ), + ]; + const doc = new DidDocument(identifier); + await doc.processMessages(messages); + + expect(doc.toJsonTree()).toEqual({ + "@context": "https://www.w3.org/ns/did/v1", + assertionMethod: [`${identifier}#did-root-key`], + authentication: [`${identifier}#did-root-key`, `${identifier}#key-3`], + id: identifier, + service: [ + { + id: `${identifier}#service-2`, + serviceEndpoint: "https://test2.identity.com", + type: "LinkedDomains", + }, + ], + verificationMethod: [ + { + controller: identifier, + id: `${identifier}#did-root-key`, + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + { + controller: identifier, + id: `${identifier}#key-3`, + publicKeyBase58: Hashing.base58.encode(key3.publicKey.toBytes()), + type: "Ed25519VerificationKey2018", + }, + ], + }); + expect(doc.getCreated()).toBeTruthy(); + expect(doc.getUpdated()).toBeTruthy(); + expect(doc.getDeactivated()).toEqual(false); + expect(doc.getVersionId()).toBeTruthy(); + }); + }); +}); diff --git a/test/unit/did-parser.test.ts b/test/unit/did-parser.test.ts new file mode 100644 index 0000000..9e16070 --- /dev/null +++ b/test/unit/did-parser.test.ts @@ -0,0 +1,39 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidParser, Hashing } from "../../dist"; + +describe("DidParser", () => { + it("throw an error when invalid did string provided", async () => { + [ + "", + "invalidDid1", + "did:invalid", + "did:invalidMethod:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.24352", + "did:hedera:invalidNetwork:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.24352", + "did:hedera:testnet:invalidAddress_0.0.24352_1.5.23462345", + "did:hedera:testnet_1.5.23462345", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:unknown:parameter=1_missing", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.1=1", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:hedera:testnet:fid", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:unknownPart_0.0.1", + "did:notHedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.1", + ].forEach((did) => { + expect(() => { + DidParser.parse(did); + }).toThrowError(); + }); + }); + + it("should part string did and provide HcsDid object", async () => { + const privateKey = PrivateKey.generate(); + + const publickeybytes = privateKey.publicKey.toBytes(); + const base58btcEncodedString = Hashing.multibase.encode(publickeybytes); + + [ + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.29643290", + `did:hedera:testnet:${base58btcEncodedString}_0.0.1`, + ].forEach((did) => { + expect(DidParser.parse(did)).toBeDefined(); + }); + }); +}); diff --git a/test/unit/event/document/hcs-did-create-did-document-event.test.ts b/test/unit/event/document/hcs-did-create-did-document-event.test.ts new file mode 100644 index 0000000..d2a4dfd --- /dev/null +++ b/test/unit/event/document/hcs-did-create-did-document-event.test.ts @@ -0,0 +1,98 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidCreateDidDocumentEvent } from "../../../../dist"; + +describe("HcsDidCreateDidDocumentEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const cid = "QmaBcDeFgHiJkLmNoP"; + const url = `https://ipfs.io/ifs/${cid}`; + const event = new HcsDidCreateDidDocumentEvent(identifier, cid, url); + + describe("#constructor", () => { + it("throws error if id is null", () => { + expect(() => new HcsDidCreateDidDocumentEvent(null as any, cid)).toThrow( + new DidError("Validation failed. DID Document args are missing") + ); + }); + + it("throws error if cid is null", () => { + expect(() => new HcsDidCreateDidDocumentEvent(identifier, null as any)).toThrow( + new DidError("Validation failed. DID Document args are missing") + ); + }); + + it("throws error if id is not valid", () => { + expect(() => new HcsDidCreateDidDocumentEvent("example", cid)).toThrow( + new DidError("DID string is invalid: topic ID is missing") + ); + }); + }); + + describe("#getId", () => { + it("returns the id that was passed via constructor", () => { + expect(event.getId()).toEqual(identifier); + }); + }); + + describe("#getType", () => { + it("returns DIDDocument", () => { + expect(event.getType()).toEqual("DIDDocument"); + }); + }); + + describe("#getCid", () => { + it("returns the cid that was passed via constructor", () => { + expect(event.getCid()).toEqual(cid); + }); + }); + + describe("#getUrl", () => { + it("returns the url that was passed via constructor", () => { + expect(event.getUrl()).toEqual(url); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON tree", () => { + expect(event.toJsonTree()).toEqual({ + DIDDocument: { + id: identifier, + type: "DIDDocument", + cid, + url, + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified version of JSON tree", () => { + expect(event.toJSON()).toEqual( + '{"DIDDocument":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","type":"DIDDocument","cid":"QmaBcDeFgHiJkLmNoP","url":"https://ipfs.io/ifs/QmaBcDeFgHiJkLmNoP"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds the HcsDidCreateDidDocumentEvent", () => { + const eventFromJson = HcsDidCreateDidDocumentEvent.fromJsonTree({ + id: identifier, + type: "DIDDocument", + cid, + url, + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidCreateDidDocumentEvent); + expect(event.toJsonTree()).toEqual({ + DIDDocument: { + id: identifier, + type: "DIDDocument", + cid, + url, + }, + }); + }); + }); +}); diff --git a/test/unit/event/document/hcs-did-delete-event.test.ts b/test/unit/event/document/hcs-did-delete-event.test.ts new file mode 100644 index 0000000..e78d754 --- /dev/null +++ b/test/unit/event/document/hcs-did-delete-event.test.ts @@ -0,0 +1,42 @@ +import { HcsDidDeleteEvent, HcsDidEventTargetName } from "../../../../dist"; + +describe("HcsDidDeleteEvent", () => { + const event = new HcsDidDeleteEvent(); + + describe("#constructor", () => { + it("targets DID document", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.Document); + }); + }); + + describe("#getId", () => { + it("returns undefined", () => { + expect(event.getId()).toBeUndefined(); + }); + }); + + describe("#toJsonTree", () => { + it("returns null", () => { + expect(event.toJsonTree()).toEqual(null); + }); + }); + + describe("#toJSON", () => { + it("returns stringified null", () => { + expect(event.toJSON()).toEqual("null"); + }); + }); + + describe("#getBase64", () => { + it("returns null", () => { + expect(event.getBase64()).toEqual(null); + }); + }); + + describe("#fromJsonTree", () => { + it("returns event object", () => { + const eventFromJson = HcsDidDeleteEvent.fromJsonTree(null); + expect(eventFromJson).toBeInstanceOf(HcsDidDeleteEvent); + }); + }); +}); diff --git a/test/unit/event/hcs-did-event-parser.test.ts b/test/unit/event/hcs-did-event-parser.test.ts new file mode 100644 index 0000000..fccf7e2 --- /dev/null +++ b/test/unit/event/hcs-did-event-parser.test.ts @@ -0,0 +1,47 @@ +import { DidMethodOperation, Hashing, HcsDidDeleteEvent } from "../../../src"; +import { HcsDidEventParser } from "../../../src/identity/hcs/did/event/hcs-did-event-parser"; + +describe("HcsDidEventParser", () => { + describe("#fromBase64", () => { + it("HcsDidDeleteEvent if operation is DELETE", () => { + const result = HcsDidEventParser.fromBase64(DidMethodOperation.DELETE, null); + expect(result).toBeInstanceOf(HcsDidDeleteEvent); + }); + + it("HcsDidDeleteEvent if operation is DELETE - ignores base64 data", () => { + const eventBase64 = Hashing.base64.encode('{"data":"data"}'); + const result = HcsDidEventParser.fromBase64(DidMethodOperation.DELETE, eventBase64); + expect(result).toBeInstanceOf(HcsDidDeleteEvent); + }); + + it("returns null if operation was not found in the map", () => { + const eventBase64 = Hashing.base64.encode('{"data":"data"}'); + const result = HcsDidEventParser.fromBase64("invalid" as any, eventBase64); + expect(result).toBeNull(); + }); + + it("returns null if event target name was not found in the map", () => { + const eventBase64 = Hashing.base64.encode('{"data":"data"}'); + const result = HcsDidEventParser.fromBase64(DidMethodOperation.CREATE, eventBase64); + expect(result).toBeNull(); + }); + + it("returns null if data is not an object", () => { + const eventBase64 = Hashing.base64.encode("invalid"); + const result = HcsDidEventParser.fromBase64(DidMethodOperation.CREATE, eventBase64); + expect(result).toBeNull(); + }); + + it("returns null if event target data is null", () => { + const eventBase64 = Hashing.base64.encode('{"Service":null}'); + const result = HcsDidEventParser.fromBase64(DidMethodOperation.CREATE, eventBase64); + expect(result).toBeNull(); + }); + + it("returns null if event target data is empty", () => { + const eventBase64 = Hashing.base64.encode('{"Service":{}}'); + const result = HcsDidEventParser.fromBase64(DidMethodOperation.UPDATE, eventBase64); + expect(result).toBeNull(); + }); + }); +}); diff --git a/test/unit/event/owner/hcs-did-create-did-owner-event.test.ts b/test/unit/event/owner/hcs-did-create-did-owner-event.test.ts new file mode 100644 index 0000000..9abd30b --- /dev/null +++ b/test/unit/event/owner/hcs-did-create-did-owner-event.test.ts @@ -0,0 +1,144 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidCreateDidOwnerEvent, HcsDidEventTargetName } from "../../../../dist"; + +describe("HcsDidCreateDidOwnerEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey); + + describe("#constructor", () => { + it("targets DIDOwner", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.DID_OWNER); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidCreateDidOwnerEvent(null, identifier, privateKey.publicKey); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. DID Owner args are missing"); + }); + + it("throws error if controller is null", () => { + let error; + try { + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", null, privateKey.publicKey); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. DID Owner args are missing"); + }); + + it("throws error if publicKey is null", () => { + let error; + try { + new HcsDidCreateDidOwnerEvent(identifier + "#did-root-key", identifier, null); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. DID Owner args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidCreateDidOwnerEvent(identifier, identifier, privateKey.publicKey); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#did-root-key"); + }); + }); + + describe("#getId", () => { + it("returns id that was passed via constructor", () => { + expect(event.getId()).toEqual(identifier + "#did-root-key"); + }); + }); + + describe("#getType", () => { + it("returns Ed25519VerificationKey2018", () => { + expect(event.getType()).toEqual("Ed25519VerificationKey2018"); + }); + }); + + describe("#getController", () => { + it("returns identifier passed via constructor", () => { + expect(event.getController()).toEqual(identifier); + }); + }); + + describe("#getPublicKey", () => { + it("returns public key instance passed via constructor", () => { + expect(event.getPublicKey()).toEqual(privateKey.publicKey); + }); + }); + + describe("#getPublicKeyBase58", () => { + it("returns base58 encoded publicKey", () => { + expect(event.getPublicKeyBase58()).toEqual("AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"); + }); + }); + + describe("#getBase64", () => { + it("returns event encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJESURPd25lciI6eyJpZCI6ImRpZDpoZWRlcmE6dGVzdG5ldDp6QUVFeEQyM3Y5d3JFVVZIS3ZiN3RpSm1BTUdDcUhveFc4eXFXTnlGdzNTWENfMC4wLjI5NjEzMzI3I2RpZC1yb290LWtleSIsInR5cGUiOiJFZDI1NTE5VmVyaWZpY2F0aW9uS2V5MjAxOCIsImNvbnRyb2xsZXIiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyIsInB1YmxpY0tleUJhc2U1OCI6IkFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON tree", () => { + expect(event.toJsonTree()).toEqual({ + DIDOwner: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified version of JSON tree", () => { + expect(event.toJSON()).toEqual( + '{"DIDOwner":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key","type":"Ed25519VerificationKey2018","controller":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","publicKeyBase58":"AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidCreateDidOwnerEvent object", () => { + const eventFromJson = HcsDidCreateDidOwnerEvent.fromJsonTree({ + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidCreateDidOwnerEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + DIDOwner: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); +}); diff --git a/test/unit/event/owner/hcs-did-update-did-owner-event.test.ts b/test/unit/event/owner/hcs-did-update-did-owner-event.test.ts new file mode 100644 index 0000000..886c1c0 --- /dev/null +++ b/test/unit/event/owner/hcs-did-update-did-owner-event.test.ts @@ -0,0 +1,144 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidUpdateDidOwnerEvent } from "../../../../dist"; + +describe("HcsDidUpdateDidOwnerEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidUpdateDidOwnerEvent(identifier + "#did-root-key", identifier, privateKey.publicKey); + + describe("#constructor", () => { + it("targets DIDOwner", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.DID_OWNER); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidUpdateDidOwnerEvent(null, identifier, privateKey.publicKey); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. DID Owner args are missing"); + }); + + it("throws error if controller is null", () => { + let error; + try { + new HcsDidUpdateDidOwnerEvent(identifier + "#did-root-key", null, privateKey.publicKey); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. DID Owner args are missing"); + }); + + it("throws error if publicKey is null", () => { + let error; + try { + new HcsDidUpdateDidOwnerEvent(identifier + "#did-root-key", identifier, null); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. DID Owner args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidUpdateDidOwnerEvent(identifier, identifier, privateKey.publicKey); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#did-root-key"); + }); + }); + + describe("#getId", () => { + it("returns id that was passed via constructor", () => { + expect(event.getId()).toEqual(identifier + "#did-root-key"); + }); + }); + + describe("#getType", () => { + it("returns Ed25519VerificationKey2018", () => { + expect(event.getType()).toEqual("Ed25519VerificationKey2018"); + }); + }); + + describe("#getController", () => { + it("returns identifier passed via constructor", () => { + expect(event.getController()).toEqual(identifier); + }); + }); + + describe("#getPublicKey", () => { + it("returns public key instance passed via constructor", () => { + expect(event.getPublicKey()).toEqual(privateKey.publicKey); + }); + }); + + describe("#getPublicKeyBase58", () => { + it("returns base58 encoded publicKey", () => { + expect(event.getPublicKeyBase58()).toEqual("AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"); + }); + }); + + describe("#getBase64", () => { + it("returns event encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJESURPd25lciI6eyJpZCI6ImRpZDpoZWRlcmE6dGVzdG5ldDp6QUVFeEQyM3Y5d3JFVVZIS3ZiN3RpSm1BTUdDcUhveFc4eXFXTnlGdzNTWENfMC4wLjI5NjEzMzI3I2RpZC1yb290LWtleSIsInR5cGUiOiJFZDI1NTE5VmVyaWZpY2F0aW9uS2V5MjAxOCIsImNvbnRyb2xsZXIiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyIsInB1YmxpY0tleUJhc2U1OCI6IkFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON tree", () => { + expect(event.toJsonTree()).toEqual({ + DIDOwner: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified version of JSON tree", () => { + expect(event.toJSON()).toEqual( + '{"DIDOwner":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key","type":"Ed25519VerificationKey2018","controller":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","publicKeyBase58":"AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidUpdateDidOwnerEvent object", () => { + const eventFromJson = HcsDidUpdateDidOwnerEvent.fromJsonTree({ + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidUpdateDidOwnerEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + DIDOwner: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#did-root-key", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); +}); diff --git a/test/unit/event/service/hcs-did-create-service-event.test.ts b/test/unit/event/service/hcs-did-create-service-event.test.ts new file mode 100644 index 0000000..4e8750f --- /dev/null +++ b/test/unit/event/service/hcs-did-create-service-event.test.ts @@ -0,0 +1,135 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidCreateServiceEvent, HcsDidEventTargetName } from "../../../../dist"; + +describe("HcsDidCreateServiceEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidCreateServiceEvent( + identifier + "#service-1", + "DIDCommMessaging", + "https://vc.test.service.com" + ); + + describe("#constructor", () => { + it("targets Service", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.SERVICE); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidCreateServiceEvent(null, "DIDCommMessaging", "https://vc.test.service.com"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if type is null", () => { + let error; + try { + new HcsDidCreateServiceEvent(identifier + "#service-1", null, "https://vc.test.service.com"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if serviceEndpoint is null", () => { + let error; + try { + new HcsDidCreateServiceEvent(identifier + "#service-1", "DIDCommMessaging", null); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidCreateServiceEvent(identifier, "DIDCommMessaging", "https://vc.test.service.com"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#service-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1" + ); + }); + }); + + describe("#getType", () => { + it("returns type passed via constructor", () => { + expect(event.getType()).toEqual("DIDCommMessaging"); + }); + }); + + describe("#getServiceEndpoint", () => { + it("returns endpoint passed via constructor", () => { + expect(event.getServiceEndpoint()).toEqual("https://vc.test.service.com"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJTZXJ2aWNlIjp7ImlkIjoiZGlkOmhlZGVyYTp0ZXN0bmV0OnpBRUV4RDIzdjl3ckVVVkhLdmI3dGlKbUFNR0NxSG94Vzh5cVdOeUZ3M1NYQ18wLjAuMjk2MTMzMjcjc2VydmljZS0xIiwidHlwZSI6IkRJRENvbW1NZXNzYWdpbmciLCJzZXJ2aWNlRW5kcG9pbnQiOiJodHRwczovL3ZjLnRlc3Quc2VydmljZS5jb20ifX0=" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + Service: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + serviceEndpoint: "https://vc.test.service.com", + type: "DIDCommMessaging", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"Service":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1","type":"DIDCommMessaging","serviceEndpoint":"https://vc.test.service.com"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidCreateServiceEvent object", () => { + const eventFromJson = HcsDidCreateServiceEvent.fromJsonTree({ + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + serviceEndpoint: "https://vc.test.service.com", + type: "DIDCommMessaging", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidCreateServiceEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + Service: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + serviceEndpoint: "https://vc.test.service.com", + type: "DIDCommMessaging", + }, + }); + }); + }); +}); diff --git a/test/unit/event/service/hcs-did-revoke-service-event.test.ts b/test/unit/event/service/hcs-did-revoke-service-event.test.ts new file mode 100644 index 0000000..4459208 --- /dev/null +++ b/test/unit/event/service/hcs-did-revoke-service-event.test.ts @@ -0,0 +1,87 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidRevokeServiceEvent } from "../../../../dist"; + +describe("HcsDidRevokeServiceEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidRevokeServiceEvent(identifier + "#service-1"); + + describe("#constructor", () => { + it("targets Service", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.SERVICE); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidRevokeServiceEvent(""); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidRevokeServiceEvent(identifier); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#service-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1" + ); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJTZXJ2aWNlIjp7ImlkIjoiZGlkOmhlZGVyYTp0ZXN0bmV0OnpBRUV4RDIzdjl3ckVVVkhLdmI3dGlKbUFNR0NxSG94Vzh5cVdOeUZ3M1NYQ18wLjAuMjk2MTMzMjcjc2VydmljZS0xIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + Service: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + }, + }); + }); + }); + + describe("#toJSON", () => { + expect(event.toJSON()).toEqual( + '{"Service":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1"}}' + ); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidRevokeServiceEvent object", () => { + const eventFromJson = HcsDidRevokeServiceEvent.fromJsonTree({ + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidRevokeServiceEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + Service: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + }, + }); + }); + }); +}); diff --git a/test/unit/event/service/hcs-did-update-service-event.test.ts b/test/unit/event/service/hcs-did-update-service-event.test.ts new file mode 100644 index 0000000..83a646c --- /dev/null +++ b/test/unit/event/service/hcs-did-update-service-event.test.ts @@ -0,0 +1,133 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidUpdateServiceEvent } from "../../../../dist"; + +describe("HcsDidUpdateServiceEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidUpdateServiceEvent( + identifier + "#service-1", + "DIDCommMessaging", + "https://vc.test.service.com" + ); + + describe("#constructor", () => { + it("targets Service", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.SERVICE); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidUpdateServiceEvent(null, "DIDCommMessaging", "https://vc.test.service.com"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if type is null", () => { + let error; + try { + new HcsDidUpdateServiceEvent(identifier + "#service-1", null, "https://vc.test.service.com"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if serviceEndpoint is null", () => { + let error; + try { + new HcsDidUpdateServiceEvent(identifier + "#service-1", "DIDCommMessaging", null); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Services args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidUpdateServiceEvent(identifier, "DIDCommMessaging", "https://vc.test.service.com"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#service-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1" + ); + }); + }); + + describe("#getType", () => { + it("returns type passed via constructor", () => { + expect(event.getType()).toEqual("DIDCommMessaging"); + }); + }); + + describe("#getServiceEndpoint", () => { + it("returns endpoint passed via constructor", () => { + expect(event.getServiceEndpoint()).toEqual("https://vc.test.service.com"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJTZXJ2aWNlIjp7ImlkIjoiZGlkOmhlZGVyYTp0ZXN0bmV0OnpBRUV4RDIzdjl3ckVVVkhLdmI3dGlKbUFNR0NxSG94Vzh5cVdOeUZ3M1NYQ18wLjAuMjk2MTMzMjcjc2VydmljZS0xIiwidHlwZSI6IkRJRENvbW1NZXNzYWdpbmciLCJzZXJ2aWNlRW5kcG9pbnQiOiJodHRwczovL3ZjLnRlc3Quc2VydmljZS5jb20ifX0=" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + Service: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + serviceEndpoint: "https://vc.test.service.com", + type: "DIDCommMessaging", + }, + }); + }); + }); + + describe("#toJSON", () => { + expect(event.toJSON()).toEqual( + '{"Service":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1","type":"DIDCommMessaging","serviceEndpoint":"https://vc.test.service.com"}}' + ); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidUpdateServiceEvent object", () => { + const eventFromJson = HcsDidUpdateServiceEvent.fromJsonTree({ + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + serviceEndpoint: "https://vc.test.service.com", + type: "DIDCommMessaging", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidUpdateServiceEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + Service: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#service-1", + serviceEndpoint: "https://vc.test.service.com", + type: "DIDCommMessaging", + }, + }); + }); + }); +}); diff --git a/test/unit/event/verification-method/hcs-did-create-verification-method-event.test.ts b/test/unit/event/verification-method/hcs-did-create-verification-method-event.test.ts new file mode 100644 index 0000000..57ecc7c --- /dev/null +++ b/test/unit/event/verification-method/hcs-did-create-verification-method-event.test.ts @@ -0,0 +1,190 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidCreateVerificationMethodEvent, HcsDidEventTargetName } from "../../../../dist"; + +describe("HcsDidCreateVerificationMethodEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + + describe("#constructor", () => { + it("targets verificationMethod", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.VERIFICATION_METHOD); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidCreateVerificationMethodEvent( + null, + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if type is null", () => { + let error; + try { + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + null, + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if controller is null", () => { + let error; + try { + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + null, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if publicKey is null", () => { + let error; + try { + new HcsDidCreateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + null + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidCreateVerificationMethodEvent( + identifier, + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#key-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1" + ); + }); + }); + + describe("#getType", () => { + it("returns type passed via constructor", () => { + expect(event.getType()).toEqual("Ed25519VerificationKey2018"); + }); + }); + + describe("#getController", () => { + it("returns type passed via constructor", () => { + expect(event.getController()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327" + ); + }); + }); + + describe("#getPublicKey", () => { + it("returns public key passed via constructor", () => { + expect(event.getPublicKey()).toEqual(privateKey.publicKey); + }); + }); + + describe("#getPublicKeyBase58", () => { + it("returns public key base58 encoded", () => { + expect(event.getPublicKeyBase58()).toEqual("AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJWZXJpZmljYXRpb25NZXRob2QiOnsiaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyNrZXktMSIsInR5cGUiOiJFZDI1NTE5VmVyaWZpY2F0aW9uS2V5MjAxOCIsImNvbnRyb2xsZXIiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyIsInB1YmxpY0tleUJhc2U1OCI6IkFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + VerificationMethod: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"VerificationMethod":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1","type":"Ed25519VerificationKey2018","controller":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","publicKeyBase58":"AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidCreateVerificationMethodEvent object", () => { + const eventFromJson = HcsDidCreateVerificationMethodEvent.fromJsonTree({ + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidCreateVerificationMethodEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + VerificationMethod: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); +}); diff --git a/test/unit/event/verification-method/hcs-did-revoke-verification-method-event.test.ts b/test/unit/event/verification-method/hcs-did-revoke-verification-method-event.test.ts new file mode 100644 index 0000000..22bd65a --- /dev/null +++ b/test/unit/event/verification-method/hcs-did-revoke-verification-method-event.test.ts @@ -0,0 +1,89 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidRevokeVerificationMethodEvent } from "../../../../dist"; + +describe("HcsDidRevokeVerificationMethodEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidRevokeVerificationMethodEvent(identifier + "#key-1"); + + describe("#constructor", () => { + it("targets verificationMethod", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.VERIFICATION_METHOD); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidRevokeVerificationMethodEvent(""); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidRevokeVerificationMethodEvent(identifier); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#key-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1" + ); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJWZXJpZmljYXRpb25NZXRob2QiOnsiaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyNrZXktMSJ9fQ==" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + VerificationMethod: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"VerificationMethod":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidRevokeVerificationMethodEvent object", () => { + const eventFromJson = HcsDidRevokeVerificationMethodEvent.fromJsonTree({ + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidRevokeVerificationMethodEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + VerificationMethod: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + }, + }); + }); + }); +}); diff --git a/test/unit/event/verification-method/hcs-did-update-verification-method-event.test.ts b/test/unit/event/verification-method/hcs-did-update-verification-method-event.test.ts new file mode 100644 index 0000000..05c77a3 --- /dev/null +++ b/test/unit/event/verification-method/hcs-did-update-verification-method-event.test.ts @@ -0,0 +1,190 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidUpdateVerificationMethodEvent } from "../../../../dist"; + +describe("HcsDidUpdateVerificationMethodEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidUpdateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + + describe("#constructor", () => { + it("targets verificationMethod", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.VERIFICATION_METHOD); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidUpdateVerificationMethodEvent( + null, + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if type is null", () => { + let error; + try { + new HcsDidUpdateVerificationMethodEvent( + identifier + "#key-1", + null, + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if controller is null", () => { + let error; + try { + new HcsDidUpdateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + null, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error publicKey id is null", () => { + let error; + try { + new HcsDidUpdateVerificationMethodEvent( + identifier + "#key-1", + "Ed25519VerificationKey2018", + identifier, + null + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Method args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidUpdateVerificationMethodEvent( + identifier, + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#key-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1" + ); + }); + }); + + describe("#getType", () => { + it("returns type passed via constructor", () => { + expect(event.getType()).toEqual("Ed25519VerificationKey2018"); + }); + }); + + describe("#getController", () => { + it("returns type passed via constructor", () => { + expect(event.getController()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327" + ); + }); + }); + + describe("#getPublicKey", () => { + it("returns public key passed via constructor", () => { + expect(event.getPublicKey()).toEqual(privateKey.publicKey); + }); + }); + + describe("#getPublicKeyBase58", () => { + it("returns public key base58 encoded", () => { + expect(event.getPublicKeyBase58()).toEqual("AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJWZXJpZmljYXRpb25NZXRob2QiOnsiaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyNrZXktMSIsInR5cGUiOiJFZDI1NTE5VmVyaWZpY2F0aW9uS2V5MjAxOCIsImNvbnRyb2xsZXIiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyIsInB1YmxpY0tleUJhc2U1OCI6IkFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + VerificationMethod: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"VerificationMethod":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1","type":"Ed25519VerificationKey2018","controller":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","publicKeyBase58":"AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidUpdateVerificationMethodEvent object", () => { + const eventFromJson = HcsDidUpdateVerificationMethodEvent.fromJsonTree({ + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidUpdateVerificationMethodEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + VerificationMethod: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); +}); diff --git a/test/unit/event/verification-relationship/hcs-did-create-verification-relationship-event.test.ts b/test/unit/event/verification-relationship/hcs-did-create-verification-relationship-event.test.ts new file mode 100644 index 0000000..3501ffc --- /dev/null +++ b/test/unit/event/verification-relationship/hcs-did-create-verification-relationship-event.test.ts @@ -0,0 +1,223 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidCreateVerificationRelationshipEvent, HcsDidEventTargetName } from "../../../../dist"; + +describe("HcsDidCreateVerificationRelationshipEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + + describe("#constructor", () => { + it("targets verificationMethod", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.VERIFICATION_RELATIONSHIP); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidCreateVerificationRelationshipEvent( + null, + "authentication", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if relationshipType is null", () => { + let error; + try { + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-1", + null, + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if type is null", () => { + let error; + try { + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + null, + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if controller is null", () => { + let error; + try { + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + "Ed25519VerificationKey2018", + null, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if publicKey is null", () => { + let error; + try { + new HcsDidCreateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + "Ed25519VerificationKey2018", + identifier, + null + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidCreateVerificationRelationshipEvent( + identifier, + "authentication", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#key-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1" + ); + }); + }); + + describe("#getType", () => { + it("returns type passed via constructor", () => { + expect(event.getType()).toEqual("Ed25519VerificationKey2018"); + }); + }); + + describe("#getRelationshipType", () => { + it("returns relationshipType passed via constructor", () => { + expect(event.getRelationshipType()).toEqual("authentication"); + }); + }); + + describe("#getController", () => { + it("returns type passed via constructor", () => { + expect(event.getController()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327" + ); + }); + }); + + describe("#getPublicKey", () => { + it("returns public key passed via constructor", () => { + expect(event.getPublicKey()).toEqual(privateKey.publicKey); + }); + }); + + describe("#getPublicKeyBase58", () => { + it("returns public key base58 encoded", () => { + expect(event.getPublicKeyBase58()).toEqual("AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJWZXJpZmljYXRpb25SZWxhdGlvbnNoaXAiOnsiaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyNrZXktMSIsInJlbGF0aW9uc2hpcFR5cGUiOiJhdXRoZW50aWNhdGlvbiIsInR5cGUiOiJFZDI1NTE5VmVyaWZpY2F0aW9uS2V5MjAxOCIsImNvbnRyb2xsZXIiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyIsInB1YmxpY0tleUJhc2U1OCI6IkFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + VerificationRelationship: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"VerificationRelationship":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1","relationshipType":"authentication","type":"Ed25519VerificationKey2018","controller":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","publicKeyBase58":"AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidCreateVerificationRelationshipEvent object", () => { + const eventFromJson = HcsDidCreateVerificationRelationshipEvent.fromJsonTree({ + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidCreateVerificationRelationshipEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + VerificationRelationship: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); +}); diff --git a/test/unit/event/verification-relationship/hcs-did-revoke-verification-relationship-event.test.ts b/test/unit/event/verification-relationship/hcs-did-revoke-verification-relationship-event.test.ts new file mode 100644 index 0000000..e1a35c5 --- /dev/null +++ b/test/unit/event/verification-relationship/hcs-did-revoke-verification-relationship-event.test.ts @@ -0,0 +1,110 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidRevokeVerificationRelationshipEvent } from "../../../../dist"; + +describe("HcsDidRevokeVerificationRelationshipEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidRevokeVerificationRelationshipEvent(identifier + "#key-1", "authentication"); + + describe("#constructor", () => { + it("targets verificationMethod", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.VERIFICATION_RELATIONSHIP); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidRevokeVerificationRelationshipEvent("", "authentication"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if relationshipType is null", () => { + let error; + try { + new HcsDidRevokeVerificationRelationshipEvent(identifier + "#key-1", null); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidRevokeVerificationRelationshipEvent(identifier, "authentication"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#key-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1" + ); + }); + }); + + describe("#getRelationshipType", () => { + it("returns relationshipType passed via constructor", () => { + expect(event.getRelationshipType()).toEqual("authentication"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJWZXJpZmljYXRpb25SZWxhdGlvbnNoaXAiOnsiaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyNrZXktMSIsInJlbGF0aW9uc2hpcFR5cGUiOiJhdXRoZW50aWNhdGlvbiJ9fQ==" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + VerificationRelationship: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + relationshipType: "authentication", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"VerificationRelationship":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1","relationshipType":"authentication"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidRevokeVerificationRelationshipEvent object", () => { + const eventFromJson = HcsDidRevokeVerificationRelationshipEvent.fromJsonTree({ + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + relationshipType: "authentication", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidRevokeVerificationRelationshipEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + VerificationRelationship: { + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + relationshipType: "authentication", + }, + }); + }); + }); +}); diff --git a/test/unit/event/verification-relationship/hcs-did-update-verification-relationship-event.test.ts b/test/unit/event/verification-relationship/hcs-did-update-verification-relationship-event.test.ts new file mode 100644 index 0000000..28c8ef4 --- /dev/null +++ b/test/unit/event/verification-relationship/hcs-did-update-verification-relationship-event.test.ts @@ -0,0 +1,223 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { DidError, Hashing, HcsDidEventTargetName, HcsDidUpdateVerificationRelationshipEvent } from "../../../../dist"; + +describe("HcsDidUpdateVerificationRelationshipEvent", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b6570042204209044d8f201e4b0aa7ba8ed577b0334b8cb6e38aad6c596171b5b1246737f5079" + ); + const identifier = `did:hedera:testnet:${Hashing.multibase.encode(privateKey.publicKey.toBytes())}_0.0.29613327`; + const event = new HcsDidUpdateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + + describe("#constructor", () => { + it("targets verificationMethod", () => { + expect(event.targetName).toEqual(HcsDidEventTargetName.VERIFICATION_RELATIONSHIP); + }); + + it("throws error if id is null", () => { + let error; + try { + new HcsDidUpdateVerificationRelationshipEvent( + "", + "authentication", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if relationshipType is null", () => { + let error; + try { + new HcsDidUpdateVerificationRelationshipEvent( + identifier + "#key-1", + null, + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if type is null", () => { + let error; + try { + new HcsDidUpdateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + null, + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if controller is null", () => { + let error; + try { + new HcsDidUpdateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + "Ed25519VerificationKey2018", + "", + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if publicKey is null", () => { + let error; + try { + new HcsDidUpdateVerificationRelationshipEvent( + identifier + "#key-1", + "authentication", + "Ed25519VerificationKey2018", + identifier, + null + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Validation failed. Verification Relationship args are missing"); + }); + + it("throws error if id is not valid", () => { + let error; + try { + new HcsDidUpdateVerificationRelationshipEvent( + identifier, + "authentication", + "Ed25519VerificationKey2018", + identifier, + privateKey.publicKey + ); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("Event ID is invalid. Expected format: {did}#key-{integer}"); + }); + }); + + describe("#getId", () => { + it("returns id passed via constructor", () => { + expect(event.getId()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1" + ); + }); + }); + + describe("#getType", () => { + it("returns type passed via constructor", () => { + expect(event.getType()).toEqual("Ed25519VerificationKey2018"); + }); + }); + + describe("#getRelationshipType", () => { + it("returns relationshipType passed via constructor", () => { + expect(event.getRelationshipType()).toEqual("authentication"); + }); + }); + + describe("#getController", () => { + it("returns type passed via constructor", () => { + expect(event.getController()).toEqual( + "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327" + ); + }); + }); + + describe("#getPublicKey", () => { + it("returns public key passed via constructor", () => { + expect(event.getPublicKey()).toEqual(privateKey.publicKey); + }); + }); + + describe("#getPublicKeyBase58", () => { + it("returns public key base58 encoded", () => { + expect(event.getPublicKeyBase58()).toEqual("AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"); + }); + }); + + describe("#getBase64", () => { + it("returns event data encoded in base64", () => { + expect(event.getBase64()).toEqual( + "eyJWZXJpZmljYXRpb25SZWxhdGlvbnNoaXAiOnsiaWQiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyNrZXktMSIsInJlbGF0aW9uc2hpcFR5cGUiOiJhdXRoZW50aWNhdGlvbiIsInR5cGUiOiJFZDI1NTE5VmVyaWZpY2F0aW9uS2V5MjAxOCIsImNvbnRyb2xsZXIiOiJkaWQ6aGVkZXJhOnRlc3RuZXQ6ekFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDXzAuMC4yOTYxMzMyNyIsInB1YmxpY0tleUJhc2U1OCI6IkFFRXhEMjN2OXdyRVVWSEt2Yjd0aUptQU1HQ3FIb3hXOHlxV055RnczU1hDIn19" + ); + }); + }); + + describe("#toJsonTree", () => { + it("returns event JSON structure", () => { + expect(event.toJsonTree()).toEqual({ + VerificationRelationship: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); + + describe("#toJSON", () => { + it("returns stringified JSON structure version", () => { + expect(event.toJSON()).toEqual( + '{"VerificationRelationship":{"id":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1","relationshipType":"authentication","type":"Ed25519VerificationKey2018","controller":"did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327","publicKeyBase58":"AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC"}}' + ); + }); + }); + + describe("#fromJsonTree", () => { + it("rebuilds HcsDidUpdateVerificationRelationshipEvent object", () => { + const eventFromJson = HcsDidUpdateVerificationRelationshipEvent.fromJsonTree({ + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + }); + + expect(eventFromJson).toBeInstanceOf(HcsDidUpdateVerificationRelationshipEvent); + expect(eventFromJson.toJsonTree()).toEqual({ + VerificationRelationship: { + controller: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327", + id: "did:hedera:testnet:zAEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC_0.0.29613327#key-1", + publicKeyBase58: "AEExD23v9wrEUVHKvb7tiJmAMGCqHoxW8yqWNyFw3SXC", + relationshipType: "authentication", + type: "Ed25519VerificationKey2018", + }, + }); + }); + }); +}); diff --git a/test/unit/hashing.test.ts b/test/unit/hashing.test.ts new file mode 100644 index 0000000..a7324a5 --- /dev/null +++ b/test/unit/hashing.test.ts @@ -0,0 +1,16 @@ +import { PrivateKey } from "@hashgraph/sdk"; +import { Hashing } from "../../dist"; + +describe("Util Multibase", () => { + it("Test Valid Multibase base58btc with ed25519 pub key encode", async () => { + const privateKey = PrivateKey.generate(); + + const publickeybytes = privateKey.publicKey.toBytes(); + const base58btcEncodedString = Hashing.multibase.encode(publickeybytes); + const decodedPublicKeyBytes = Hashing.multibase.decode(base58btcEncodedString); + + // z is for base58btc + expect(base58btcEncodedString.startsWith("z")).toBeTruthy(); + expect(decodedPublicKeyBytes).toStrictEqual(publickeybytes); + }); +}); diff --git a/test/unit/hcs-did-message.test.ts b/test/unit/hcs-did-message.test.ts new file mode 100644 index 0000000..3109233 --- /dev/null +++ b/test/unit/hcs-did-message.test.ts @@ -0,0 +1,110 @@ +import { Client, PrivateKey, TopicId } from "@hashgraph/sdk"; +import { DidMethodOperation, Hashing, HcsDid, HcsDidCreateDidOwnerEvent, HcsDidMessage } from "../../dist"; + +const network = "testnet"; +const DID_TOPIC_ID1 = TopicId.fromString("0.0.2"); +const DID_TOPIC_ID2 = TopicId.fromString("0.0.3"); + +describe("HcsDidMessage", () => { + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + const privateKey = PrivateKey.generate(); + const identifier = `did:hedera:${network}:${Hashing.multibase.encode( + privateKey.publicKey.toBytes() + )}_${DID_TOPIC_ID1}`; + + it("Test Valid Message", () => { + const did = new HcsDid({ identifier: identifier, privateKey: privateKey, client: client }); + + const message = new HcsDidMessage( + DidMethodOperation.CREATE, + did.getIdentifier(), + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + expect(message.isValid(DID_TOPIC_ID1)).toEqual(true); + }); + + it("Test Invalid Did", () => { + const did = new HcsDid({ identifier: identifier, privateKey: privateKey, client: client }); + + const message = new HcsDidMessage( + DidMethodOperation.CREATE, + "invalid_did###", + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + expect(message.isValid()).toEqual(false); + }); + + it("Test Invalid Topic", () => { + const did = new HcsDid({ identifier: identifier, privateKey: privateKey, client: client }); + + const message = new HcsDidMessage( + DidMethodOperation.CREATE, + did.getIdentifier(), + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + expect(message.isValid(DID_TOPIC_ID1)).toEqual(true); + expect(message.isValid(DID_TOPIC_ID2)).toEqual(false); + }); + + it("Test Missing Data", () => { + const did = new HcsDid({ identifier: identifier, privateKey: privateKey, client: client }); + + let message = new HcsDidMessage( + null, + did.getIdentifier(), + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + expect(message.getOperation()).toEqual(null); + expect(message.isValid()).toEqual(false); + + message = new HcsDidMessage( + DidMethodOperation.CREATE, + null, + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + expect(message.getDid()).toEqual(null); + expect(message.isValid()).toEqual(false); + + message = new HcsDidMessage(DidMethodOperation.CREATE, did.getIdentifier(), null); + + expect(message.getEvent()).toEqual(null); + expect(message.isValid()).toEqual(false); + + message = new HcsDidMessage( + DidMethodOperation.CREATE, + did.getIdentifier(), + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + expect(message.isValid()).toEqual(true); + }); +}); diff --git a/test/unit/hcs-did-transaction.test.ts b/test/unit/hcs-did-transaction.test.ts new file mode 100644 index 0000000..c81091e --- /dev/null +++ b/test/unit/hcs-did-transaction.test.ts @@ -0,0 +1,51 @@ +import { Client, Hbar, PrivateKey, TopicId } from "@hashgraph/sdk"; +import { + DidMethodOperation, + Hashing, + HcsDid, + HcsDidCreateDidOwnerEvent, + HcsDidMessage, + HcsDidTransaction, + MessageEnvelope, +} from "../../dist"; + +describe("HcsDidTransaction", () => { + const network = "testnet"; + const DID_TOPIC_ID1 = TopicId.fromString("0.0.2"); + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + const privateKey = PrivateKey.generate(); + const identifier = `did:hedera:${network}:${Hashing.multibase.encode( + privateKey.publicKey.toBytes() + )}_${DID_TOPIC_ID1}`; + const TRANSACTION_FEE = new Hbar(2); + + describe("execute", () => { + const did = new HcsDid({ identifier: identifier, privateKey: privateKey, client: client }); + const message = new HcsDidMessage( + DidMethodOperation.CREATE, + "invalid_did###", + new HcsDidCreateDidOwnerEvent( + did.getIdentifier() + "#did-root-key", + did.getIdentifier(), + privateKey.publicKey + ) + ); + + const envelope = new MessageEnvelope(message); + const transaction = new HcsDidTransaction(envelope, DID_TOPIC_ID1); + + it("Validation Errors: signing & Transaction builder function missing", async () => { + await expect(transaction.execute(client)).rejects.toThrow( + "MessageTransaction execution failed: :\nSigning function is missing.\nTransaction builder is missing." + ); + }); + + it("Validation Errors: Transaction builder function missing", async () => { + await expect(transaction.signMessage((msg) => privateKey.sign(msg)).execute(client)).rejects.toThrow( + "MessageTransaction execution failed: :\nTransaction builder is missing." + ); + }); + + //TODO: mock dependencies and test submitTransaction + }); +}); diff --git a/test/unit/hsc-did.test.ts b/test/unit/hsc-did.test.ts new file mode 100644 index 0000000..b91839d --- /dev/null +++ b/test/unit/hsc-did.test.ts @@ -0,0 +1,161 @@ +import { Client, PrivateKey } from "@hashgraph/sdk"; +import { DidError, HcsDid } from "../../dist"; + +describe("HcsDid", () => { + let client; + + beforeAll(async () => { + client = Client.forTestnet({ scheduleNetworkUpdate: false }); + }); + describe("#constructor", () => { + it("throws error because of missing identifier and privateKey", () => { + expect(() => new HcsDid({})).toThrowError(new DidError("identifier and privateKey cannot both be empty")); + }); + + it("successfully builds HcsDid with private key only", () => { + const privateKey = PrivateKey.generate(); + const did = new HcsDid({ privateKey }); + + expect(did.getIdentifier()).toEqual(undefined); + expect(did.getPrivateKey()).toEqual(privateKey); + expect(did.getClient()).toEqual(undefined); + expect(did.getTopicId()).toEqual(undefined); + expect(did.getNetwork()).toEqual(undefined); + }); + + it("successfully builds HcsDid with identifier only", () => { + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier }); + + expect(did.getIdentifier()).toEqual(identifier); + expect(did.getPrivateKey()).toEqual(undefined); + expect(did.getClient()).toEqual(undefined); + expect(did.getTopicId().toString()).toEqual("0.0.29613327"); + expect(did.getNetwork()).toEqual("testnet"); + }); + + it("throws error if passed identifier is invalid", () => { + [ + "", + "invalidDid1", + "did:invalid", + "did:invalidMethod:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.24352", + "did:hedera:invalidNetwork:8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.24352", + "did:hedera:testnet:invalidAddress_0.0.24352_1.5.23462345", + "did:hedera:testnet_1.5.23462345", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:unknown:parameter=1_missing", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.1=1", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:hedera:testnet:fid", + "did:hedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak:unknownPart_0.0.1", + "did:notHedera:testnet:z6Mk8LjUL78kFVnWV9rFnNCTE5bZdRmjm2obqJwS892jVLak_0.0.1", + ].forEach((identifier) => { + expect(() => { + new HcsDid({ identifier }); + }).toThrowError(); + }); + }); + + it("accepts client parameter", () => { + const client = Client.forTestnet({ scheduleNetworkUpdate: false }); + const identifier = "did:hedera:testnet:z6MkgUv5CvjRP6AsvEYqSRN7djB6p4zK9bcMQ93g5yK6Td7N_0.0.29613327"; + const did = new HcsDid({ identifier, client }); + + expect(did.getIdentifier()).toEqual(identifier); + expect(did.getPrivateKey()).toEqual(undefined); + expect(did.getClient()).toEqual(client); + expect(did.getTopicId().toString()).toEqual("0.0.29613327"); + expect(did.getNetwork()).toEqual("testnet"); + }); + }); + describe("#parseIdentifier", () => { + it("throws error if topicId missing", () => { + let error; + try { + HcsDid.parseIdentifier("did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID string is invalid: topic ID is missing"); + }); + + it("throws error if invalid prefix", () => { + let error; + try { + HcsDid.parseIdentifier("abcd:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.1"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID string is invalid: invalid prefix."); + }); + + it("throws error if invalid method name", () => { + let error; + try { + HcsDid.parseIdentifier("did:hashgraph:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.1"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID string is invalid: invalid method name: hashgraph"); + }); + + it("throws error if Invalid Hedera network", () => { + let error; + try { + HcsDid.parseIdentifier("did:hedera:nonetwork:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.1"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID string is invalid. Invalid Hedera network."); + }); + + it("throws error if Invalid id string", () => { + let error; + try { + HcsDid.parseIdentifier("did:hedera:testnet:z6Mkabcd_0.0.1"); + } catch (err) { + error = err; + } + + expect(error).toBeInstanceOf(DidError); + expect(error.message).toEqual("DID string is invalid. ID holds incorrect format."); + }); + + it("should get array with NetworkName, topicId and didIdString", () => { + const [networkName, topicId, didIdString] = HcsDid.parseIdentifier( + "did:hedera:testnet:z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb_0.0.1" + ); + + expect(networkName).toEqual("testnet"); + expect(topicId.toString()).toEqual("0.0.1"); + expect(didIdString).toEqual("z87meAWt7t2zrDxo7qw3PVTjexKWReYWS75LH29THy8kb"); + }); + }); + + describe("#publicKeyToIdString", () => { + it("should get DID Id String from publicKey", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" + ); + const result = HcsDid.publicKeyToIdString(privateKey.publicKey); + expect(result).toEqual("zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo"); + }); + }); + + describe("#stringToPublicKey", () => { + it("should get publicKey from DID Id String", () => { + const privateKey = PrivateKey.fromString( + "302e020100300506032b657004220420a4b76d7089dfd33c83f586990c3a36ae92fb719fdf262e7749d1b0ddd1d055b0" + ); + const result = HcsDid.stringToPublicKey("zGkqFaR7Y3ZLDJJiFyfC24W8wWdsSN6tVig6KLgxaaujo"); + expect(result).toEqual(privateKey.publicKey); + }); + }); +}); diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 0000000..e756d76 --- /dev/null +++ b/test/utils.ts @@ -0,0 +1,51 @@ +import { Timestamp, TopicMessage, TopicMessageQuery } from "@hashgraph/sdk"; + +export function delay(time) { + return new Promise((resolve) => setTimeout(resolve, time)); +} + +export async function delayUntil(condition: () => Promise, timeoutMs: number): Promise { + return new Promise(async (resolve) => { + const startTime = Date.now(); + + const checkCondition = async () => { + try { + const isConditionMet = await condition(); + + if (isConditionMet) { + resolve(true); + } else if (Date.now() - startTime >= timeoutMs) { + resolve(false); + } else { + setTimeout(checkCondition, 3000); + } + } catch (error) { + resolve(false); + } + }; + + checkCondition(); + }); +} + +export async function readTopicMessages(topicId, client) { + const messages: TopicMessage[] = []; + + const query = new TopicMessageQuery() + .setTopicId(topicId) + .setStartTime(new Timestamp(0, 0)) + .setEndTime(Timestamp.fromDate(new Date())); + + query.setMaxBackoff(2000); + query.setMaxAttempts(5); + + const querySubcription = query.subscribe(client, null, (msg) => { + messages.push(msg); + }); + + await delay(2000); + + querySubcription.unsubscribe(); + + return messages; +} diff --git a/test/variables.js b/test/variables.js deleted file mode 100644 index 1a50948..0000000 --- a/test/variables.js +++ /dev/null @@ -1,34 +0,0 @@ -const OPERATOR_ID = process.env.OPERATOR_ID; -const OPERATOR_KEY = process.env.OPERATOR_KEY; -// testnet, previewnet, mainnet -const NETWORK = process.env.NETWORK || 'testnet'; - -// hedera, kabuto (note kabuto not available on previewnet) -const MIRROR_PROVIDER = process.env.MIRROR_PROVIDER || 'hedera'; - -if (!OPERATOR_ID || !/^\d+\.\d+\.\d+$/.test(OPERATOR_ID)) { - console.error('Missing or invalid OPERATOR_ID'); - process.exit(1); -} - -if (!OPERATOR_KEY) { - console.error('Missing required OPERATOR_KEY'); - process.exit(1); -} - -if (!NETWORK || !/^(mainnet|previewnet|testnet)$/.test(NETWORK)) { - console.error('Missing or invalid NETWORK'); - process.exit(1); -} - -if (!MIRROR_PROVIDER || !/^(hedera|kabuto)$/.test(MIRROR_PROVIDER)) { - console.error('Missing or invalid MIRROR_PROVIDER'); - process.exit(1); -} - -module.exports = { - OPERATOR_ID, - OPERATOR_KEY, - NETWORK, - MIRROR_PROVIDER -} diff --git a/test/vc/demo-access-credential.js b/test/vc/demo-access-credential.js deleted file mode 100644 index e68a7eb..0000000 --- a/test/vc/demo-access-credential.js +++ /dev/null @@ -1,79 +0,0 @@ -const { - CredentialSubject -} = require("../../dist"); - -/** - * Example Credential. - */ -class DemoAccessCredential extends CredentialSubject { - static ACCESS_GRANTED = "granted"; - static ACCESS_DENIED = "denied"; - - blueLevel; - greenLevel; - redLevel; - - /** - * Creates a new credential instance. - * - * @param did Credential Subject DID. - * @param blue Access to blue level granted or denied. - * @param green Access to green level granted or denied. - * @param red Access to red level granted or denied. - */ - constructor(did, blue, green, red) { - super(); - this.id = did; - this.blueLevel = blue ? DemoAccessCredential.ACCESS_GRANTED : DemoAccessCredential.ACCESS_DENIED; - this.greenLevel = green ? DemoAccessCredential.ACCESS_GRANTED : DemoAccessCredential.ACCESS_DENIED; - this.redLevel = red ? DemoAccessCredential.ACCESS_GRANTED : DemoAccessCredential.ACCESS_DENIED; - } - - getBlueLevel() { - return this.blueLevel; - } - - getGreenLevel() { - return this.greenLevel; - } - - getRedLevel() { - return this.redLevel; - } - - toJsonTree() { - const json = super.toJsonTree(); - json["blueLevel"] = this.blueLevel; - json["greenLevel"] = this.greenLevel; - json["redLevel"] = this.redLevel; - return json; - } - - toJson() { - return JSON.stringify(this.toJsonTree()); - } - - static fromJsonTree(json) { - const result = new DemoAccessCredential(null, null, null, null); - super.fromJsonTree(json, result); - result.blueLevel = json["blueLevel"]; - result.greenLevel = json["greenLevel"]; - result.redLevel = json["redLevel"]; - return result; - } - - static fromJson(json) { - const root = JSON.parse(json); - return this.fromJsonTree(root); - } - - static toJsonTree(item) { - return item ? item.toJsonTree() : null; - } - - static toJson(item) { - return JSON.stringify(this.toJsonTree(item)); - } -} - -exports.DemoAccessCredential = DemoAccessCredential; diff --git a/test/vc/demo-verifiable-credential-document.js b/test/vc/demo-verifiable-credential-document.js deleted file mode 100644 index 728e1e0..0000000 --- a/test/vc/demo-verifiable-credential-document.js +++ /dev/null @@ -1,24 +0,0 @@ -const { - HcsVcDocumentBase -} = require("../../dist"); - -/** - * Custom VC document for tests. - */ -class DemoVerifiableCredentialDocument extends HcsVcDocumentBase { - customProperty; - - constructor() { - super(); - } - - getCustomProperty() { - return this.customProperty; - } - - setCustomProperty(customProperty) { - this.customProperty = customProperty; - } -} - -exports.DemoVerifiableCredentialDocument = DemoVerifiableCredentialDocument; \ No newline at end of file diff --git a/test/vc/hcs-vc-document-base-test.js b/test/vc/hcs-vc-document-base-test.js deleted file mode 100644 index fac0dd6..0000000 --- a/test/vc/hcs-vc-document-base-test.js +++ /dev/null @@ -1,139 +0,0 @@ -const { - HcsVcDocumentBase, - Issuer -} = require("../../dist"); -const { - Timestamp -} = require('@hashgraph/sdk'); -const { - DemoAccessCredential -} = require("./demo-access-credential"); -const { - DemoVerifiableCredentialDocument -} = require("./demo-verifiable-credential-document"); -const { - NetworkReadyTestBase -} = require("../network-ready-test-base"); - -const { expect, assert } = require('chai'); - -describe("HcsVcDocumentBaseTest", function () { - const network = new NetworkReadyTestBase(); - let issuer, owner; - - before(async function () { - this.timeout(60000); - await network.setup(); - - issuer = network.didNetwork.generateDid(false); - owner = network.didNetwork.generateDid(false); - }); - - after(async function () { - network.cleanup(); - }); - - it('Test VcDocumentConstruction', async function () { - const vc = new HcsVcDocumentBase(); - - // Should fail as no issuer is set. - assert.isFalse(vc.isComplete()); - - vc.setIssuer(issuer); - - // Should fail as no issuance date is set. - assert.isFalse(vc.isComplete()); - - vc.setIssuanceDate(Timestamp.fromDate(new Date())); - - // Should fail as no credential subject is set. - assert.isFalse(vc.isComplete()); - - // Default VC type should be set. - assert.exists(vc.getType()); - assert.equal(1, vc.getType().length); - - // Add a custom type - vc.addType("TestVC"); - assert.equal(2, vc.getType().length); - - // Default context should be set - assert.exists(vc.getContext()); - assert.equal(1, vc.getContext().length); - - // Add a custom context - vc.addContext("https://www.example.com/testContext"); - assert.equal(2, vc.getContext().length); - - // Add a credential subject. - assert.notExists(vc.getCredentialSubject()); - const credential = new DemoAccessCredential(owner.toDid(), true, false, false); - vc.addCredentialSubject(credential); - - // Make sure it's there - assert.exists(vc.getCredentialSubject()); - assert.equal(1, vc.getCredentialSubject().length); - - // Now all mandatory fields should be set - assert.isTrue(vc.isComplete()); - }); - - - it('Test VcJsonConversion', async function () { - const vc = new HcsVcDocumentBase(); - vc.setId("example:test:vc:id"); - vc.setIssuer(new Issuer(issuer.toDid(), "My Company Ltd.")); - vc.setIssuanceDate(Timestamp.fromDate(new Date())); - - const subject = new DemoAccessCredential(owner.toDid(), true, false, false); - vc.addCredentialSubject(subject); - - // Convert to JSON - const json = vc.toJSON(); - assert.isFalse(!(json)); - - // Convert back to VC document and compare - const vcFromJson = HcsVcDocumentBase.fromJson(json, DemoAccessCredential); - // Test simple properties - assert.exists(vcFromJson); - assert.deepEqual(vc.getType(), vcFromJson.getType()); - assert.deepEqual(vc.getContext(), vcFromJson.getContext()); - assert.deepEqual(vc.getIssuanceDate(), vcFromJson.getIssuanceDate()); - assert.equal(vc.getId(), vcFromJson.getId()); - - // Test issuer object - assert.exists(vcFromJson.getIssuer()); - assert.equal(vc.getIssuer().getId(), vcFromJson.getIssuer().getId()); - assert.equal(vc.getIssuer().getName(), vcFromJson.getIssuer().getName()); - - // Test credential subject - assert.exists(vcFromJson.getCredentialSubject()); - - const subjectFromJson = vcFromJson.getCredentialSubject()[0]; - assert.equal(subject.getId(), subjectFromJson.getId()); - assert.equal(subject.getBlueLevel(), subjectFromJson.getBlueLevel()); - assert.equal(subject.getGreenLevel(), subjectFromJson.getGreenLevel()); - assert.equal(subject.getRedLevel(), subjectFromJson.getRedLevel()); - }); - - it('Test CredentialHash', async function () { - const vc = new DemoVerifiableCredentialDocument(); - vc.setId("example:test:vc:id"); - vc.setIssuer(issuer); - vc.setIssuanceDate(Timestamp.fromDate(new Date())); - vc.addCredentialSubject(new DemoAccessCredential(owner.toDid(), true, false, false)); - vc.setCustomProperty("Custom property value 1"); - - const credentialHash = vc.toCredentialHash(); - assert.isFalse(!credentialHash); - - // Recalculation should give the same value - assert.equal(credentialHash, vc.toCredentialHash()); - - // Hash shall not change if we don't change anything in the document - vc.setCustomProperty("Another value for custom property"); - vc.addCredentialSubject(new DemoAccessCredential(owner.toDid(), false, false, true)); - - assert.equal(credentialHash, vc.toCredentialHash()); - }); -}); diff --git a/test/vc/hcs-vc-document-operations-test.js b/test/vc/hcs-vc-document-operations-test.js deleted file mode 100644 index abf0372..0000000 --- a/test/vc/hcs-vc-document-operations-test.js +++ /dev/null @@ -1,122 +0,0 @@ - -const { - HcsVcDocumentBase, - HcsVcOperation -} = require("../../dist"); -const { - Timestamp -} = require('@hashgraph/sdk'); -const { - DemoAccessCredential -} = require("./demo-access-credential"); -const { - NetworkReadyTestBase -} = require("../network-ready-test-base"); - -const { expect, assert } = require('chai'); - - -/** - * Tests operations on verifiable credentials and their status resolution. - */ -describe("HcsVcDocumentOperationsTest", function () { - const network = new NetworkReadyTestBase(); - let issuer, owner, vc, credentialHash, issuersPrivateKey; - - before(async function () { - this.timeout(60000); - await network.setup(); - - issuer = network.didNetwork.generateDid(false); - issuersPrivateKey = issuer.getPrivateDidRootKey(); - - owner = network.didNetwork.generateDid(false); - - // For tests only we do not need to submit DID documents, as we will not validate them. - // final DidMethodOperation op = DidMethodOperation.CREATE; - // sendDidTransaction(issuer, issuer.generateDidDocument().toJson(), op, EXPECT_NO_ERROR); - // sendDidTransaction(owner, owner.generateDidDocument().toJson(), op, EXPECT_NO_ERROR); - - // Create an example Verifiable Credential. - vc = new HcsVcDocumentBase(); - vc.setIssuer(issuer); - vc.setIssuanceDate(Timestamp.fromDate(new Date())); - vc.addCredentialSubject(new DemoAccessCredential(owner.toDid(), true, false, false)); - - credentialHash = vc.toCredentialHash(); - }); - - after(async function () { - network.cleanup(); - }); - - const EXPECT_NO_ERROR = function (err) { - assert.notExists(err); - }; - - const testVcOperation = async function (op) { - const envelope = await network.sendVcTransaction(op, credentialHash, issuersPrivateKey, EXPECT_NO_ERROR); - - assert.exists(envelope); - - const msg = envelope.open(); - - // Check results - assert.exists(msg); - assert.isTrue(msg.isValid()); - assert.equal(op, msg.getOperation()); - assert.equal(credentialHash, msg.getCredentialHash()); - } - - const testVcStatusResolution = async function (expectedOperation) { - const envelope = await network.resolveVcStatus( - credentialHash, - (m) => [issuersPrivateKey.publicKey], - EXPECT_NO_ERROR - ); - - assert.exists(envelope); - - const msg = envelope.open(); - - assert.exists(msg); - assert.isTrue(msg.isValid()); - assert.equal(credentialHash, msg.getCredentialHash()); - assert.equal(expectedOperation, msg.getOperation()); - } - - it('Test Issue', async function () { - this.timeout(60000); - await testVcOperation(HcsVcOperation.ISSUE); - await testVcStatusResolution(HcsVcOperation.ISSUE); - }); - - it('Test Suspend', async function () { - this.timeout(60000); - await testVcOperation(HcsVcOperation.SUSPEND); - await testVcStatusResolution(HcsVcOperation.SUSPEND); - }); - - it('Test Resume', async function () { - this.timeout(60000); - await testVcOperation(HcsVcOperation.RESUME); - await testVcStatusResolution(HcsVcOperation.RESUME); - }); - - it('Test Revoke', async function () { - this.timeout(60000); - await testVcOperation(HcsVcOperation.REVOKE); - await testVcStatusResolution(HcsVcOperation.REVOKE); - }); - - it('Test InvalidResumeAfterRevoke', async function () { - this.timeout(120000); - await testVcOperation(HcsVcOperation.RESUME); - // Status should still be revoked - await testVcStatusResolution(HcsVcOperation.REVOKE); - - await testVcOperation(HcsVcOperation.SUSPEND); - // Status should still be revoked - await testVcStatusResolution(HcsVcOperation.REVOKE); - }); -}); \ No newline at end of file diff --git a/test/vc/hcs-vc-encryption-test.js b/test/vc/hcs-vc-encryption-test.js deleted file mode 100644 index 980e9c0..0000000 --- a/test/vc/hcs-vc-encryption-test.js +++ /dev/null @@ -1,192 +0,0 @@ -const { - Hbar, Timestamp, -} = require('@hashgraph/sdk'); - -const { - HcsVcDocumentBase, - HcsVcOperation, - HcsVcMessage, - MessageEnvelope, - ArraysUtils -} = require("../../dist"); -const { - DemoAccessCredential -} = require("./demo-access-credential"); -const { - DemoVerifiableCredentialDocument -} = require("./demo-verifiable-credential-document"); -const { - NetworkReadyTestBase, until, sleep -} = require("../network-ready-test-base"); -const { - encrypt, decrypt -} = require("../aes-encryption-util"); - -const { expect, assert } = require('chai'); - -/** - * Tests operations on verifiable credentials and their status resolution. - */ -describe("HcsVcEncryptionTest", function () { - const MIRROR_NODE_TIMEOUT = 30 * 1000; - const NO_MORE_MESSAGES_TIMEOUT = 15 * 1000; - const FEE = new Hbar(2); - const SECRET = "Secret message used for encryption"; - const INVALID_SECRET = "Invalid secret message used for decryption"; - const network = new NetworkReadyTestBase(); - let issuer, owner, vc, credentialHash, issuersPrivateKey; - - const EXPECT_NO_ERROR = function (err) { - assert.notExists(err); - }; - - before(async function () { - this.timeout(120000); - await network.setup(); - - issuer = network.didNetwork.generateDid(false); - issuersPrivateKey = issuer.getPrivateDidRootKey(); - - owner = network.didNetwork.generateDid(false); - - // For tests only we do not need to submit DID documents, as we will not validate them. - // final DidMethodOperation op = DidMethodOperation.CREATE; - // sendDidTransaction(issuer, issuer.generateDidDocument().toJson(), op, EXPECT_NO_ERROR); - // sendDidTransaction(owner, owner.generateDidDocument().toJson(), op, EXPECT_NO_ERROR); - - // Create an example Verifiable Credential. - vc = new HcsVcDocumentBase(); - vc.setIssuer(issuer); - vc.setIssuanceDate(Timestamp.fromDate(new Date())); - vc.addCredentialSubject(new DemoAccessCredential(owner.toDid(), true, false, false)); - - credentialHash = vc.toCredentialHash(); - - await sleep(1000); - }); - - after(async function () { - network.cleanup(); - }); - - it('Test IssueValidEncryptedMessage', async function () { - this.timeout(60000); - - const messageRef = []; - - // Build and execute transaction with encrypted message - await network.didNetwork.createVcTransaction(HcsVcOperation.ISSUE, credentialHash, issuersPrivateKey.publicKey) - .signMessage(doc => issuersPrivateKey.sign(doc)) - .buildAndSignTransaction(tx => tx.setMaxTransactionFee(FEE)) - .onMessageConfirmed(msg => messageRef.push(msg)) - .onError(EXPECT_NO_ERROR) - .onEncrypt(m => encrypt(m, SECRET)) - .onDecrypt((m, i) => decrypt(m, SECRET)) - .execute(network.client); - - // Wait until consensus is reached and mirror node received the DID document, but with max. time limit. - await until(MIRROR_NODE_TIMEOUT, () => !!messageRef.length); - - const envelope = messageRef[0]; - - assert.exists(envelope); - - const msg = envelope.open(); - - // Check results - assert.exists(msg); - assert.isTrue(msg.isValid()); - assert.equal(credentialHash, msg.getCredentialHash()); - - await sleep(1000); - }); - - it('Test ResolveWithValidDecrypter', async function () { - this.timeout(60000); - - const mapRef = []; - - // Resolve encrypted message - network.didNetwork.getVcStatusResolver(m => [issuersPrivateKey.publicKey]) - .addCredentialHash(credentialHash) - .setTimeout(NO_MORE_MESSAGES_TIMEOUT) - .onError(EXPECT_NO_ERROR) - .onDecrypt((m, i) => decrypt(m, SECRET)) - .whenFinished(m => mapRef.push(m)) - .execute(network.client); - - // Wait until mirror node resolves the DID. - await until(MIRROR_NODE_TIMEOUT, () => !!mapRef.length); - - const envelope = mapRef[0] ? mapRef[0].get(credentialHash) : null; - - assert.exists(envelope); - - const msg = envelope.open(); - - // Check results - assert.exists(msg); - assert.isTrue(msg.isValid()); - assert.equal(credentialHash, msg.getCredentialHash()); - - await sleep(1000); - }); - - it('Test ResolveWithInvalidDecrypter', async function () { - this.timeout(60000); - - const mapRef = []; - const errorRef = []; - - // Try to resolve encrypted message with a wrong secret - network.didNetwork.getVcStatusResolver(m => [issuersPrivateKey.publicKey]) - .addCredentialHash(credentialHash) - .setTimeout(NO_MORE_MESSAGES_TIMEOUT) - .onError(e => errorRef.push(String(e))) - .onDecrypt((m, i) => decrypt(m, INVALID_SECRET)) - .whenFinished(m => mapRef.push(m)) - .execute(network.client); - - // Wait until mirror node resolves the DID. - await until(MIRROR_NODE_TIMEOUT, () => !!mapRef.length); - - const envelope = mapRef[0] ? mapRef[0].get(credentialHash) : null; - const error = errorRef[0]; - - assert.notExists(envelope); - assert.exists(error); - - await sleep(1000); - }); - - it('Test MessageEncryptionDecryption', async function () { - this.timeout(60000); - - const msg = HcsVcMessage.fromCredentialHash(credentialHash, HcsVcOperation.ISSUE); - - const encryptedMsg = msg - .encrypt(HcsVcMessage.getEncrypter(m => encrypt(m, SECRET))); - - assert.exists(encryptedMsg); - - - const msgJson = ArraysUtils.toString(encryptedMsg.sign(m => issuersPrivateKey.sign(m))); - const encryptedSignedMsg = MessageEnvelope.fromJson(msgJson, HcsVcMessage); - - assert.exists(encryptedSignedMsg); - // Throw error if decrypter is not provided - try { - encryptedSignedMsg.open(); - assert.fail("Throw error if decrypter is not provided"); - } catch (error) { - assert.exists(error); - } - - const decryptedMsg = encryptedSignedMsg - .open(HcsVcMessage.getDecrypter((m, i) => decrypt(m, SECRET))); - - assert.exists(decryptedMsg); - assert.equal(credentialHash, decryptedMsg.getCredentialHash()); - assert.equal(encryptedSignedMsg.open().getTimestamp(), decryptedMsg.getTimestamp()); - }); -}); \ No newline at end of file