diff --git a/README.md b/README.md index a944615..f08dd4f 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,14 @@ export INDEXING_RETRY_INTERVAL='3000' export AVOID_LOOP_RUN='true/false' ``` +- Optional, set SSI_WALLET_API, SSI_WALLET_ID, SSI_WALLET_DID to support v5 DDOs (assets using credentialSubject and SSI policy flows). + +``` +export SSI_WALLET_API="https://your-ssi-wallet.example/api" +export SSI_WALLET_ID="did:example:your-wallet-did-or-id" +export export SSI_WALLET_DID="did:example" +``` + ### Build the TypeScript code @@ -108,7 +116,7 @@ npm run cli h E.g. run publish command -Make sure to update chainId from the assets from `metadata` folder. +Make sure to update chainId and serviceEnpoint from the assets from `metadata` folder. ``` npm run cli publish metadata/simpleDownloadDataset.json @@ -186,23 +194,29 @@ npm run cli [options] **Download:** - **Positional:** - `npm run cli download did:op:123 ./custom-folder` + `npm run cli download did:op:123 ./custom-folder serviceId` - **Named Options:** - `npm run cli download --did did:op:123 --folder ./custom-folder` + `npm run cli download --did did:op:123 --folder ./custom-folder --service serviceId` (Order of `--did` and `--folder` does not matter.) +- **Rules:** + serviceId is optional. If omitted, the CLI defaults to the first available download service. + --- **Start Compute:** - **Positional:** - `npm run cli startCompute -- did1,did2 algoDid env1 maxJobDuration paymentToken resources --accept true` + `npm run cli startCompute -- did1,did2 algoDid env1 maxJobDuration paymentToken resources svc1,svc2 algoServiceId` - **Named Options:** - `npm run cli startCompute --datasets did1,did2 --algo algoDid --env env1 --maxJobDuration maxJobDuration --token paymentToken --resources resources --accept true` + `npm run cli startCompute --datasets did1,did2 --algo algoDid --env env1 --maxJobDuration maxJobDuration --token paymentToken --resources resources --accept true --services svc1,svc2 ----algo-service algoServiceId` (Options can be provided in any order.) +- **Rules:** + serviceIds and algoServiceId are optional. If omitted, the CLI defaults to the first available service. + - `maxJobDuration` is a required parameter an represents the time measured in seconds for job maximum execution, the payment is based on this maxJobDuration value, user needs to provide this. - `paymentToken` is required and represents the address of the token that is supported by the environment for processing the compute job payment. It can be retrieved from `getComputeEnvironments` command output. @@ -218,7 +232,11 @@ e.g.: `'[{"id":"cpu","amount":3},{"id":"ram","amount":16772672536},{"id":"disk", `npm run cli startFreeCompute did1,did2 algoDid env1` - **Named Options:** - `npm run cli startFreeCompute --datasets did1,did2 --algo algoDid --env env1` + `npm run cli startFreeCompute --datasets did1,did2 --algo algoDid --env env1 --services svc1,svc2 ----algo-service algoServiceId` + (Options can be provided in any order.) + +- **Rules:** + serviceIds and algoServiceId are optional. If omitted, the CLI defaults to the first available service.` (Options can be provided in any order.) --- @@ -416,6 +434,8 @@ e.g.: `'[{"id":"cpu","amount":3},{"id":"ram","amount":16772672536},{"id":"disk", - **download:** `-d, --did ` `-f, --folder [destinationFolder]` (Default: `.`) + `-s, --service ` (Optional, target a specific service) + - **startCompute:** `-d, --datasets ` @@ -426,11 +446,15 @@ e.g.: `'[{"id":"cpu","amount":3},{"id":"ram","amount":16772672536},{"id":"disk", `-t, --token ` `--resources ` `--amountToDeposit ` (Id `''`, it will fallback to initialize compute payment amount.) + `-s, --services [serviceIds]` (Optional, comma-separated; must match datasetDids length, positional 1–1) + `-x, --algo-service [algoServiceId]` (Optional, override algorithm service) - **startFreeCompute:** `-d, --datasets ` `-a, --algo ` `-e, --env ` + `-s, --services [serviceIds]` (Optional, comma-separated; must match datasetDids length, positional 1–1) + `-x, --algo-service [algoServiceId]` (Optional, override algorithm service) - **getComputeEnvironments:** diff --git a/metadata/jsAlgoV5.json b/metadata/jsAlgoV5.json new file mode 100644 index 0000000..b88d45a --- /dev/null +++ b/metadata/jsAlgoV5.json @@ -0,0 +1,199 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2" + ], + "id": "did:ope", + "version": "5.0.0", + "credentialSubject": { + "chainId": 8996, + "metadata": { + "created": "2025-09-09T11:57:52Z", + "updated": "2025-09-09T11:57:52Z", + "type": "algorithm", + "name": "cli algo test", + "description": { + "@value": "testing algo", + "@direction": "", + "@language": "" + }, + "tags": [ + "test" + ], + "author": "", + "license": { + "name": "https://raw.githubusercontent.com/oceanprotocol/c2d-examples/main/branin_and_gpr/branin.arff", + "licenseDocuments": [ + { + "sha256": "71a828f4ddc3fee436d80fc5b02535fc5e13ae8f19eae87ec02734bb01126c5b", + "mirrors": [ + { + "method": "get", + "type": "url", + "url": "https://raw.githubusercontent.com/oceanprotocol/c2d-examples/main/branin_and_gpr/branin.arff" + } + ], + "name": "https://raw.githubusercontent.com/oceanprotocol/c2d-examples/main/branin_and_gpr/branin.arff", + "fileType": "text/plain; charset=utf-8" + } + ] + }, + "links": {}, + "additionalInformation": { + "termsAndConditions": true + }, + "algorithm": { + "language": "arff", + "version": "0.1", + "container": { + "entrypoint": "node $ALGO", + "image": "node", + "tag": "latest", + "checksum": "sha256:c3688c7b5cc3b159ddf4f744594de62461df7ef43124378f118cb470e4f72bcb" + } + }, + "copyrightHolder": "", + "providedBy": "" + }, + "services": [ + { + "compute": { + "publisherTrustedAlgorithms": [], + "publisherTrustedAlgorithmPublishers": [ + "*" + ], + "allowRawAlgorithm": false, + "allowNetworkAccess": true + }, + "credentials": { + "allow": [ + { + "values": [ + { + "request_credentials": [ + { + "format": "jwt_vc_json", + "policies": [], + "type": "UniversityDegree" + } + ], + "vc_policies": [ + "not-before", + "revoked-status-list", + "signature" + ] + } + ], + "type": "SSIpolicy" + }, + { + "values": [ + { + "address": "*" + } + ], + "type": "address" + } + ], + "match_deny": "any", + "deny": [] + }, + "name": "test service", + "files": { + "datatokenAddress": "0x0", + "nftAddress": "0x0", + "files": [ + { + "type": "url", + "url": "https://raw.githubusercontent.com/oceanprotocol/c2d-examples/main/branin_and_gpr/branin.arff", + "method": "GET" + } + ] + }, + "description": { + "@value": "testing new service", + "@direction": "ltr", + "@language": "en" + }, + "id": "23033c06ea9adc6ff5dff42938417c7750e75efbdfbfecf5d6d544705450df24", + "datatokenAddress": "0x0", + "serviceEndpoint": "https://ocean-node-vm3.oceanenterprise.io", + "state": 0, + "type": "compute", + "timeout": 31556952 + } + ], + "nftAddress": "0x0", + "credentials": { + "allow": [ + { + "values": [ + { + "request_credentials": [ + { + "format": "jwt_vc_json", + "policies": [], + "type": "UniversityDegree" + } + ], + "vc_policies": [ + "not-before", + "revoked-status-list", + "signature" + ] + } + ], + "type": "SSIpolicy" + }, + { + "values": [ + { + "address": "*" + } + ], + "type": "address" + } + ], + "deny": [], + "match_deny": "any" + } + }, + "additionalDdos": [], + "type": [ + "VerifiableCredential" + ], + "issuer": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5Iiwia2lkIjoiekxlRGh1UG15QndrampiV1pRZTBPeHdEMjMxYmx3aXFTMGQ0VTJETnZFbyIsIngiOiJta3NvaEladWlsblJWWmhTbmwxNGRpdTZZWDF3UUFFX0ozbWJoWDNDOFRjIn0", + "indexedMetadata": { + "stats": [ + { + "symbol": "OEAT", + "name": "Access Token", + "orders": 0, + "datatokenAddress": "", + "serviceId": "23033c06ea9adc6ff5dff42938417c7750e75efbdfbfecf5d6d544705450df24", + "prices": [ + { + "exchangeId": "", + "price": "2.0", + "contract": "", + "type": "fixedrate", + "token": "" + } + ] + } + ], + "nft": { + "state": 0, + "address": "", + "name": "Data NFT", + "symbol": "OEC-NFT", + "owner": "", + "created": "", + "tokenURI": "" + }, + "event": { + }, + "purgatory": { + "state": false + } + } +} \ No newline at end of file diff --git a/metadata/simpleDownloadDatasetV5.json b/metadata/simpleDownloadDatasetV5.json new file mode 100644 index 0000000..14bd89c --- /dev/null +++ b/metadata/simpleDownloadDatasetV5.json @@ -0,0 +1,167 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2" + ], + "id": "did:ope", + "version": "5.0.0", + "type": ["VerifiableCredential"], + "additionalDdos": [], + "credentialSubject": { + "chainId": 8996, + "metadata": { + "created": "2025-02-19T10:23:59Z", + "updated": "2025-02-19T10:23:59Z", + "type": "dataset", + "name": "The Digital Project Management Office (DigitalPMO)", + "description": { + "@value": "fdsfsdfsdfsdfsdfsd", + "@direction": "", + "@language": "" + }, + "tags": [], + "author": "", + "license": { + "name": "https://www.google.de", + "licenseDocuments": [ + { + "name": "https://www.google.de", + "fileType": "text/html; charset=ISO-8859-1", + "sha256": "5a051e8e73057a521eadf3f80219495c4ed04d63397e5817a72ec2c335025b44", + "mirrors": [ + { + "type": "url", + "method": "get", + "url": "https://www.google.de" + } + ] + } + ] + }, + "links": {}, + "additionalInformation": { + "termsAndConditions": true + }, + "copyrightHolder": "", + "providedBy": "" + }, + "services": [ + { + "id": "ccb398c50d6abd5b456e8d7242bd856a1767a890b537c2f8c10ba8b8a10e6025", + "type": "access", + "files": { + "datatokenAddress": "0x0", + "nftAddress": "0x0", + "files": [ + { + "type": "url", + "url": "https://raw.githubusercontent.com/oceanprotocol/c2d-examples/main/branin_and_gpr/branin.arff", + "method": "GET" + } + ] + }, + "state": 0, + "datatokenAddress": "", + "serviceEndpoint": "https://ocean-node-vm3.oceanenterprise.io", + "timeout": 0, + "name": "", + "credentials": { + "allow": [ + { + "type": "address", + "values": [ + { + "address": "*" + } + ] + } + ], + "deny": [], + "match_deny": "any" + } + } + ], + "credentials": { + "allow": [ + { + "type": "SSIpolicy", + "values": [ + { + "request_credentials": [ + { + "format": "jwt_vc_json", + "policies": [], + "type": "UniversityDegree" + } + ], + "vc_policies": [ + "signature", + "not-before", + "revoked-status-list" + ], + "vp_policies": [ + { + "policy": "holder-binding" + }, + { + "policy": "presentation-definition" + }, + { + "policy": "minimum-credentials", + "args": "1" + }, + { + "policy": "maximum-credentials", + "args": "2" + } + ] + } + ] + }, + { + "type": "address", + "values": [ + { + "address": "*" + } + ] + } + ], + "deny": [], + "match_deny": "any" + } + }, + "indexedMetadata": { + "stats": [ + { + "datatokenAddress": "", + "name": "Access Token", + "symbol": "OEAT", + "serviceId": "ccb398c50d6abd5b456e8d7242bd856a1767a890b537c2f8c10ba8b8a10e6025", + "orders": 0, + "prices": [ + { + "type": "dispenser", + "price": "0", + "contract": "", + "token": "" + } + ] + } + ], + "nft": { + "state": 0, + "address": "", + "name": "Data NFT", + "symbol": "OEC-NFT", + "owner": "", + "created": "", + "tokenURI": "" + }, + "event": { + }, + "purgatory": { + "state": false + } + }, + "issuer": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5Iiwia2lkIjoibUJjZDJXbGQ0YVNCaHpJR0RKNTVPc1NHWUY4R2h6Vmt2MkVkTC1KYko5MCIsIngiOiJJT1R2UWRqQlRxMzZMbTFuTXdkaTYzN00zdXMycUR3blN5MC13djVkNFRBIn0" +} diff --git a/package-lock.json b/package-lock.json index e2d2d56..805d2c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@oceanprotocol/contracts": "^2.5.0", "@oceanprotocol/ddo-js": "^0.1.4", "@oceanprotocol/lib": "^6.0.0", + "axios": "^1.11.0", "commander": "^13.1.0", "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", @@ -53,28 +54,14 @@ "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "license": "MIT" }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -83,9 +70,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", "engines": { @@ -93,22 +80,22 @@ } }, "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -134,14 +121,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -164,13 +151,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -208,18 +195,18 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "engines": { @@ -240,14 +227,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", - "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "regexpu-core": "^6.2.0", + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "engines": { @@ -268,17 +255,17 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", + "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" + "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -295,43 +282,43 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -354,9 +341,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -382,15 +369,15 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -424,9 +411,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -444,42 +431,42 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", - "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", + "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", - "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.0" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -489,14 +476,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", - "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -556,14 +543,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", - "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -601,13 +588,13 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz", - "integrity": "sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.28.6.tgz", + "integrity": "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -617,13 +604,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", - "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", + "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -633,13 +620,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -662,13 +649,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -711,15 +698,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", - "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", + "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.29.0" }, "engines": { "node": ">=6.9.0" @@ -729,14 +716,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", - "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", + "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { @@ -763,13 +750,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz", - "integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", + "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -779,14 +766,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", - "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -796,14 +783,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", - "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", + "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -813,18 +800,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", - "integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", + "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -834,14 +821,14 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", - "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", + "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/template": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/template": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -851,14 +838,14 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.0.tgz", - "integrity": "sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -868,14 +855,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", - "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", + "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -901,14 +888,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -934,14 +921,14 @@ } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", - "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -951,13 +938,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", - "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", + "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1035,13 +1022,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", - "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", + "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1067,13 +1054,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", - "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", + "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1116,14 +1103,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", - "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1133,16 +1120,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", - "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", + "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.29.0" }, "engines": { "node": ">=6.9.0" @@ -1169,14 +1156,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1202,13 +1189,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", - "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1218,13 +1205,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", - "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", + "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1234,17 +1221,17 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz", - "integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", + "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1271,13 +1258,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", - "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", + "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1287,13 +1274,13 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", - "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { @@ -1320,14 +1307,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", - "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1337,15 +1324,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", - "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", + "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1387,17 +1374,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", - "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz", + "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-jsx": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1440,13 +1427,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.1.tgz", - "integrity": "sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", + "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1456,14 +1443,14 @@ } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", - "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1505,13 +1492,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", - "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", + "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { @@ -1586,14 +1573,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", - "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", + "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1620,14 +1607,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", - "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", + "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -1637,81 +1624,81 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.0.tgz", - "integrity": "sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", + "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", + "@babel/compat-data": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.0", - "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.29.0", + "@babel/plugin-transform-async-to-generator": "^7.28.6", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.0", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.28.0", - "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.28.0", - "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.28.6", "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.0", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", "@babel/plugin-transform-member-expression-literals": "^7.27.1", "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", + "@babel/plugin-transform-modules-systemjs": "^7.29.0", "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.28.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.0", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.29.0", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", "@babel/plugin-transform-sticky-regex": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-typeof-symbol": "^7.27.1", "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1765,15 +1752,15 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz", - "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-transform-react-display-name": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" @@ -1786,9 +1773,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", - "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "dev": true, "license": "MIT", "engines": { @@ -1796,33 +1783,33 @@ } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", "debug": "^4.3.1" }, "engines": { @@ -1830,14 +1817,14 @@ } }, "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1878,17 +1865,16 @@ } }, "node_modules/@digitalbazaar/http-client": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-3.4.1.tgz", - "integrity": "sha512-Ahk1N+s7urkgj7WvvUND5f8GiWEPfUw0D41hdElaqLgu8wZScI8gdI0q+qWw5N1d35x7GCRH2uk9mi+Uzo9M3g==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-4.3.0.tgz", + "integrity": "sha512-6lMpxpt9BOmqHKGs9Xm6DP4LlZTBFer/ZjHvP3FcW3IaUWYIWC7dw5RFZnvw4fP57kAVcm1dp3IF+Y50qhBvAw==", "license": "BSD-3-Clause", "dependencies": { - "ky": "^0.33.3", - "ky-universal": "^0.11.0", - "undici": "^5.21.2" + "ky": "^1.14.2", + "undici": "^6.23.0" }, "engines": { - "node": ">=14.0" + "node": ">=18.0" } }, "node_modules/@ecies/ciphers": { @@ -1906,9 +1892,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", - "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "cpu": [ "ppc64" ], @@ -1923,9 +1909,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", - "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "cpu": [ "arm" ], @@ -1940,9 +1926,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", - "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "cpu": [ "arm64" ], @@ -1957,9 +1943,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", - "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -1974,9 +1960,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", - "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -1991,9 +1977,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", - "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "cpu": [ "x64" ], @@ -2008,9 +1994,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", - "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "cpu": [ "arm64" ], @@ -2025,9 +2011,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", - "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "cpu": [ "x64" ], @@ -2042,9 +2028,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", - "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "cpu": [ "arm" ], @@ -2059,9 +2045,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", - "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ "arm64" ], @@ -2076,9 +2062,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", - "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "cpu": [ "ia32" ], @@ -2093,9 +2079,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", - "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "cpu": [ "loong64" ], @@ -2110,9 +2096,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", - "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "cpu": [ "mips64el" ], @@ -2127,9 +2113,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", - "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "cpu": [ "ppc64" ], @@ -2144,9 +2130,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", - "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "cpu": [ "riscv64" ], @@ -2161,9 +2147,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", - "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "cpu": [ "s390x" ], @@ -2178,9 +2164,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", - "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "cpu": [ "x64" ], @@ -2195,9 +2181,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", - "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "cpu": [ "arm64" ], @@ -2212,9 +2198,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", - "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "cpu": [ "x64" ], @@ -2229,9 +2215,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", - "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "cpu": [ "arm64" ], @@ -2246,9 +2232,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", - "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "cpu": [ "x64" ], @@ -2263,9 +2249,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", - "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", "cpu": [ "arm64" ], @@ -2280,9 +2266,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", - "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "cpu": [ "x64" ], @@ -2297,9 +2283,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", - "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "cpu": [ "arm64" ], @@ -2314,9 +2300,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", - "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "cpu": [ "ia32" ], @@ -2331,9 +2317,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", - "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "cpu": [ "x64" ], @@ -2348,9 +2334,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2367,9 +2353,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -2430,9 +2416,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", - "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -2916,15 +2902,6 @@ "@ethersproject/strings": "^5.8.0" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "license": "MIT", - "engines": { - "node": ">=14" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -2964,9 +2941,9 @@ "license": "BSD-3-Clause" }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { @@ -2974,6 +2951,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -2984,9 +2972,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", - "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { @@ -2995,15 +2983,15 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -3207,9 +3195,9 @@ } }, "node_modules/@oceanprotocol/ddo-js/node_modules/chai": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", - "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", @@ -3223,9 +3211,9 @@ } }, "node_modules/@oceanprotocol/ddo-js/node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "license": "MIT", "engines": { "node": ">= 16" @@ -3241,9 +3229,9 @@ } }, "node_modules/@oceanprotocol/ddo-js/node_modules/loupe": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", - "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "license": "MIT" }, "node_modules/@oceanprotocol/ddo-js/node_modules/pathval": { @@ -3355,9 +3343,9 @@ } }, "node_modules/@rdfjs/formats/node_modules/rdfxml-streaming-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rdfxml-streaming-parser/-/rdfxml-streaming-parser-3.1.0.tgz", - "integrity": "sha512-4HJ5NbwhfT1mroMpzsI6nQHv2OYAUVI4cOsRTU7+6uBnHuYj1VTqLGbP92pcXcAYcX6H9UEOxvRHZUsF6OVgxw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/rdfxml-streaming-parser/-/rdfxml-streaming-parser-3.2.0.tgz", + "integrity": "sha512-SgQGK0EkbXd0jQ1PZk7dEpfDxf4CZpezkO6cTuGWesa9twdWaaW5elMoNBcbMT+2tOZC1EYZjs0JaXx0HnifcQ==", "license": "MIT", "dependencies": { "@rubensworks/saxes": "^6.0.1", @@ -3428,13 +3416,13 @@ } }, "node_modules/@rdfjs/serializer-jsonld-ext": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@rdfjs/serializer-jsonld-ext/-/serializer-jsonld-ext-4.0.1.tgz", - "integrity": "sha512-eGNAdhsV8wkmCadyIN+PBfsN+BIiqplAd5VMc++wf5McsVi/vPNrWcBINdrNnlegml8nLUy0rlKztCQ/4pxW8w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@rdfjs/serializer-jsonld-ext/-/serializer-jsonld-ext-4.0.2.tgz", + "integrity": "sha512-l/A6gQgKWYYGOPbcVZWnaamqWPtShL4FDrEqh5F85Fw0PdSca7q0YOBpB8ihxKmiGmfXa+SB4M8l9iyEegcp7Q==", "license": "MIT", "dependencies": { "@rdfjs/sink": "^2.0.1", - "jsonld": "^8.3.3", + "jsonld": "^9.0.0", "readable-stream": "^4.7.0", "stream-chunks": "^1.0.0" } @@ -3820,9 +3808,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", "license": "MIT" }, "node_modules/@tsconfig/node12": { @@ -3892,9 +3880,9 @@ "license": "MIT" }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", "license": "MIT", "peer": true }, @@ -3945,9 +3933,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", - "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", + "version": "20.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.31.tgz", + "integrity": "sha512-5jsi0wpncvTD33Sh1UCgacK37FFwDn+EG7wCmEvs62fCvBL+n8/76cAYDok21NF6+jaVWIqKwCZyX7Vbu8eB3A==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -4179,9 +4167,9 @@ } }, "node_modules/@types/readable-stream": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.21.tgz", - "integrity": "sha512-19eKVv9tugr03IgfXlA9UVUVRbW6IuqRO5B92Dl4a6pT7K8uaGrNS0GkxiZD0BOk6PLuXl5FhWl//eX/pzYdTQ==", + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.23.tgz", + "integrity": "sha512-wwXrtQvbMHxCbBgjHaMGEmImFTQxxpfMOR/ZoQnXxB1woqkUbdLGFDgauo00Py9IudiaqSeiBiulSV9i6XIPig==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -4208,9 +4196,9 @@ } }, "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.7.tgz", + "integrity": "sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==", "license": "MIT", "peer": true, "dependencies": { @@ -4218,9 +4206,9 @@ } }, "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "dev": true, "license": "MIT" }, @@ -4498,9 +4486,9 @@ } }, "node_modules/@zazuko/prefixes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@zazuko/prefixes/-/prefixes-2.4.0.tgz", - "integrity": "sha512-bd53k5XgFKWR56sofHeAcIbv8o0m2HsJlbHaHbrMufUCdgiZsCLvZn84Vh1dhcsyBHOD0EIo9AD4pNWDQLVRaw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@zazuko/prefixes/-/prefixes-2.6.1.tgz", + "integrity": "sha512-fbOadP7twxt0ZYT9mgIC+xQMk6f3pYYLI5a/2UJ/mc/ygqb/NoVv2ryK3lTtoi74xwkdpUeDwIuFQSosowzUgg==", "license": "MIT" }, "node_modules/@zazuko/rdf-utils-fs": { @@ -4912,9 +4900,9 @@ "license": "MIT" }, "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "version": "10.4.24", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz", + "integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==", "dev": true, "funding": [ { @@ -4932,10 +4920,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001766", + "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, @@ -4981,6 +4968,33 @@ "license": "MIT", "peer": true }, + "node_modules/axios": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz", + "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -4998,14 +5012,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", + "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.6", "semver": "^6.3.1" }, "peerDependencies": { @@ -5023,27 +5037,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", + "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@babel/helper-define-polyfill-provider": "^0.6.6", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", + "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" + "@babel/helper-define-polyfill-provider": "^0.6.6" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5106,6 +5120,16 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -5167,24 +5191,24 @@ "peer": true }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "peer": true, "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -5282,9 +5306,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -5302,10 +5326,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -5397,9 +5422,9 @@ "peer": true }, "node_modules/bufferutil": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", - "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", + "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", "hasInstallScript": true, "license": "MIT", "peer": true, @@ -5582,9 +5607,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001731", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", - "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", + "version": "1.0.30001768", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001768.tgz", + "integrity": "sha512-qY3aDRZC5nWPgHUgIB84WL+nySuo19wk0VJpp/XI9T34lrvkyhRvNVOFJOp2kxClQhiFBu+TaUSudf6oa3vkSA==", "dev": true, "funding": [ { @@ -5603,10 +5628,13 @@ "license": "CC-BY-4.0" }, "node_modules/canonicalize": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", - "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", - "license": "Apache-2.0" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.1.0.tgz", + "integrity": "sha512-F705O3xrsUtgt98j7leetNhTWPe+5S72rlL5O4jA1pKqBVQ/dT1O1D6PFxmSXvc0SUOinWS57DKx0I3CHrXJHQ==", + "license": "Apache-2.0", + "bin": { + "canonicalize": "bin/canonicalize.js" + } }, "node_modules/caseless": { "version": "0.12.0", @@ -5775,14 +5803,15 @@ } }, "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" }, "engines": { "node": ">= 0.10" @@ -5946,9 +5975,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "peer": true, "engines": { @@ -5956,20 +5985,20 @@ } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT", "peer": true }, "node_modules/core-js-compat": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.0.tgz", - "integrity": "sha512-gRoVMBawZg0OnxaVv3zpqLLxaHmsubEGyTnqdpI/CEBvX4JadI1dMSHxagThprYRtSVbuQxvi6iUatdPxohHpA==", + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", + "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.1" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -5984,9 +6013,9 @@ "peer": true }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", "peer": true, "dependencies": { @@ -5995,6 +6024,10 @@ }, "engines": { "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/cosmiconfig": { @@ -6353,9 +6386,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6543,9 +6576,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6757,9 +6790,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.195", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.195.tgz", - "integrity": "sha512-URclP0iIaDUzqcAyV1v2PgduJ9N0IdXmWsnPzPfelvBmjmZzEy6xJcjb1cXj+TbYqXgtLrjHEoaSIdTYhw4ezg==", + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "dev": true, "license": "ISC" }, @@ -6829,9 +6862,9 @@ } }, "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==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6839,9 +6872,9 @@ } }, "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, "license": "MIT", "dependencies": { @@ -6926,27 +6959,27 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz", + "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", + "es-abstract": "^1.24.1", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", + "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", + "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", + "iterator.prototype": "^1.1.5", "safe-array-concat": "^1.1.3" }, "engines": { @@ -7062,9 +7095,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", - "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7075,32 +7108,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.8", - "@esbuild/android-arm": "0.25.8", - "@esbuild/android-arm64": "0.25.8", - "@esbuild/android-x64": "0.25.8", - "@esbuild/darwin-arm64": "0.25.8", - "@esbuild/darwin-x64": "0.25.8", - "@esbuild/freebsd-arm64": "0.25.8", - "@esbuild/freebsd-x64": "0.25.8", - "@esbuild/linux-arm": "0.25.8", - "@esbuild/linux-arm64": "0.25.8", - "@esbuild/linux-ia32": "0.25.8", - "@esbuild/linux-loong64": "0.25.8", - "@esbuild/linux-mips64el": "0.25.8", - "@esbuild/linux-ppc64": "0.25.8", - "@esbuild/linux-riscv64": "0.25.8", - "@esbuild/linux-s390x": "0.25.8", - "@esbuild/linux-x64": "0.25.8", - "@esbuild/netbsd-arm64": "0.25.8", - "@esbuild/netbsd-x64": "0.25.8", - "@esbuild/openbsd-arm64": "0.25.8", - "@esbuild/openbsd-x64": "0.25.8", - "@esbuild/openharmony-arm64": "0.25.8", - "@esbuild/sunos-x64": "0.25.8", - "@esbuild/win32-arm64": "0.25.8", - "@esbuild/win32-ia32": "0.25.8", - "@esbuild/win32-x64": "0.25.8" + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, "node_modules/escalade": { @@ -7832,9 +7865,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8057,9 +8090,9 @@ } }, "node_modules/ethers": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.15.0.tgz", - "integrity": "sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz", + "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==", "funding": [ { "type": "individual", @@ -8222,40 +8255,40 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -8369,9 +8402,9 @@ "license": "MIT" }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", "dependencies": { @@ -8402,15 +8435,27 @@ } }, "node_modules/figlet": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.2.tgz", - "integrity": "sha512-iPCpE9B/rOcjewIzDnagP9F2eySzGeHReX8WlrZQJkqFBk2wvq8gY0c6U6Hd2y9HnX1LQcYSeP7aEHoPt6sVKQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.10.0.tgz", + "integrity": "sha512-aktIwEZZ6Gp9AWdMXW4YCi0J2Ahuxo67fNJRUIWD81w8pQ0t9TS8FFpbl27ChlTLF06VkwjDesZSzEVzN75rzA==", "license": "MIT", + "dependencies": { + "commander": "^14.0.0" + }, "bin": { "figlet": "bin/index.js" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 17.0.0" + } + }, + "node_modules/figlet/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" } }, "node_modules/figures": { @@ -8507,18 +8552,18 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "license": "MIT", "peer": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -8609,6 +8654,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -8681,16 +8746,16 @@ } }, "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", "dev": true, "license": "MIT", "engines": { "node": "*" }, "funding": { - "type": "patreon", + "type": "github", "url": "https://github.com/sponsors/rawify" } }, @@ -8791,6 +8856,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/generic-names": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", @@ -8903,9 +8977,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.2.tgz", + "integrity": "sha512-LwrDmz5/YSHHIrxETNzL39eyuhUffOSD43v08W+jIOzUJmku47wD7itIoOjI2BOxxa+irG3Hqj8kSD4Y/dmQ6g==", "dev": true, "license": "MIT", "dependencies": { @@ -8929,7 +9003,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -9252,35 +9326,68 @@ } }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, + "node_modules/hash-base/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT", + "peer": true + }, "node_modules/hash-base/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==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "peer": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hash-base/node_modules/readable-stream/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==", + "license": "MIT", + "peer": true + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" } }, + "node_modules/hash-base/node_modules/string_decoder/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==", + "license": "MIT", + "peer": true + }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", @@ -9334,20 +9441,24 @@ "peer": true }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "peer": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/http-https": { @@ -9829,13 +9940,14 @@ "peer": true }, "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" }, @@ -10234,9 +10346,9 @@ "license": "MIT" }, "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==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -10320,9 +10432,9 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -10333,24 +10445,24 @@ } }, "node_modules/jsonld": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-8.3.3.tgz", - "integrity": "sha512-9YcilrF+dLfg9NTEof/mJLMtbdX1RJ8dbWtJgE00cMOIohb1lIyJl710vFiTaiHTl6ZYODJuBd32xFvUhmv3kg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-9.0.0.tgz", + "integrity": "sha512-pjMIdkXfC1T2wrX9B9i2uXhGdyCmgec3qgMht+TDj+S0qX3bjWMQUfL7NeqEhuRTi8G5ESzmL9uGlST7nzSEWg==", "license": "BSD-3-Clause", "dependencies": { - "@digitalbazaar/http-client": "^3.4.1", - "canonicalize": "^1.0.1", + "@digitalbazaar/http-client": "^4.2.0", + "canonicalize": "^2.1.0", "lru-cache": "^6.0.0", - "rdf-canonize": "^3.4.0" + "rdf-canonize": "^5.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/jsonld-context-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonld-context-parser/-/jsonld-context-parser-3.0.0.tgz", - "integrity": "sha512-Kg6TVtBUdIm057ht/8WNhM9BROt+BeYaDGXbzrKaa3xA99csee+CsD8IMCTizRgzoO8PIzvzcxxCoRvpq1xNQw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonld-context-parser/-/jsonld-context-parser-3.1.0.tgz", + "integrity": "sha512-BfgNJ/t9jjK7Lun9XRCJM6YeNqDk8B6/lg+KS8rzhXAOtS0FvoClSmtLvF24V1M2CDYRy2LcEBt0ilxqSX93WA==", "license": "MIT", "dependencies": { "@types/http-link-header": "^1.0.1", @@ -10360,12 +10472,16 @@ }, "bin": { "jsonld-context-parse": "bin/jsonld-context-parse.js" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/rubensworks/" } }, "node_modules/jsonld-context-parser/node_modules/@types/node": { - "version": "18.19.121", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz", - "integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==", + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -10378,9 +10494,9 @@ "license": "MIT" }, "node_modules/jsonld-streaming-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonld-streaming-parser/-/jsonld-streaming-parser-5.0.0.tgz", - "integrity": "sha512-Q6Bfbmig8fFpIbJgJTi4LLzco9dz0YuBM/mDvUYXzP8L/+me6P3pRy4exrhCpv49Bwv2oQFFIHM7wIwCKma2XA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonld-streaming-parser/-/jsonld-streaming-parser-5.0.1.tgz", + "integrity": "sha512-Rf230DRAWe5p1H4e7phk1vo4FHEMOmC5xVcIywKJBBcwy6zaJWFcAvPcwngufNTdJs7dpTMbKQDjp4TYDpMKUQ==", "license": "MIT", "dependencies": { "@bergos/jsonparse": "^1.4.0", @@ -10389,7 +10505,7 @@ "buffer": "^6.0.3", "canonicalize": "^1.0.1", "http-link-header": "^1.0.2", - "jsonld-context-parser": "^3.0.0", + "jsonld-context-parser": "^3.1.0", "rdf-data-factory": "^2.0.0", "readable-stream": "^4.0.0" }, @@ -10398,13 +10514,19 @@ "url": "https://github.com/sponsors/rubensworks/" } }, + "node_modules/jsonld-streaming-parser/node_modules/canonicalize": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", + "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", + "license": "Apache-2.0" + }, "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "license": "MIT", "dependencies": { - "jws": "^3.2.2", + "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -10453,9 +10575,9 @@ } }, "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", @@ -10464,12 +10586,12 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -10524,60 +10646,17 @@ } }, "node_modules/ky": { - "version": "0.33.3", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz", - "integrity": "sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz", + "integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==", "license": "MIT", "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sindresorhus/ky?sponsor=1" } }, - "node_modules/ky-universal": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", - "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "node-fetch": "^3.2.10" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky-universal?sponsor=1" - }, - "peerDependencies": { - "ky": ">=0.31.4", - "web-streams-polyfill": ">=3.2.1" - }, - "peerDependenciesMeta": { - "web-streams-polyfill": { - "optional": true - } - } - }, - "node_modules/ky-universal/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -10636,9 +10715,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -11156,9 +11235,10 @@ } }, "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.2.tgz", + "integrity": "sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==", + "license": "MIT", "peer": true, "dependencies": { "dom-walk": "^0.1.0" @@ -11308,7 +11388,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -11604,9 +11684,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, "license": "MIT" }, @@ -11650,16 +11730,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -12169,55 +12239,21 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", - "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", "license": "MIT", "peer": true, "dependencies": { - "create-hash": "~1.1.3", + "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "ripemd160": "=2.0.1", + "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", - "sha.js": "^2.4.11", - "to-buffer": "^1.2.0" + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/pbkdf2/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", - "license": "MIT", - "peer": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/pbkdf2/node_modules/hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", - "license": "MIT", - "peer": true, - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/pbkdf2/node_modules/ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", - "license": "MIT", - "peer": true, - "dependencies": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" + "node": ">= 0.10" } }, "node_modules/performance-now": { @@ -12655,9 +12691,9 @@ } }, "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -12685,9 +12721,9 @@ } }, "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -12988,9 +13024,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { @@ -13116,6 +13152,13 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT", + "peer": true + }, "node_modules/promise.series": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", @@ -13152,6 +13195,12 @@ "node": ">= 0.10" } }, + "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==", + "license": "MIT" + }, "node_modules/psl": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", @@ -13185,13 +13234,13 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "peer": true, "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -13269,31 +13318,31 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "license": "MIT", "peer": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/rdf-canonize": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz", - "integrity": "sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-5.0.0.tgz", + "integrity": "sha512-g8OUrgMXAR9ys/ZuJVfBr05sPPoMA7nHIVs8VEvg9QwM5W4GR2qSFEEHjsyHF1eWlBaf8Ev40WNjQFQ+nJTO3w==", "license": "BSD-3-Clause", "dependencies": { "setimmediate": "^1.0.5" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/rdf-data-factory": { @@ -13320,6 +13369,18 @@ "readable-stream": "3 - 4" } }, + "node_modules/rdf-dataset-ext/node_modules/rdf-canonize": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz", + "integrity": "sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==", + "license": "BSD-3-Clause", + "dependencies": { + "setimmediate": "^1.0.5" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/rdf-literal": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/rdf-literal/-/rdf-literal-2.0.0.tgz", @@ -13507,9 +13568,9 @@ "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, "license": "MIT", "dependencies": { @@ -13564,18 +13625,18 @@ } }, "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", + "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", + "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "unicode-match-property-value-ecmascript": "^2.2.1" }, "engines": { "node": ">=4" @@ -13589,31 +13650,18 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~3.0.2" + "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/relative-to-absolute-iri": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/relative-to-absolute-iri/-/relative-to-absolute-iri-1.0.7.tgz", @@ -13689,13 +13737,13 @@ } }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -13788,14 +13836,17 @@ } }, "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", "license": "MIT", "peer": true, "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/rlp": { @@ -14283,9 +14334,9 @@ "peer": true }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -14295,25 +14346,25 @@ } }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "license": "MIT", "peer": true, "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -14336,16 +14387,6 @@ "license": "MIT", "peer": true }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -14357,16 +14398,16 @@ } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "license": "MIT", "peer": true, "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.19.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -14710,9 +14751,9 @@ "license": "MIT" }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "peer": true, "engines": { @@ -15187,6 +15228,7 @@ "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "peer": true, "dependencies": { @@ -15223,14 +15265,14 @@ "peer": true }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -15277,9 +15319,9 @@ } }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "license": "MIT", "peer": true, "dependencies": { @@ -15391,9 +15433,9 @@ } }, "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -15455,13 +15497,13 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.20.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", - "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.25.0", + "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -15637,9 +15679,9 @@ } }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -15928,15 +15970,12 @@ } }, "node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, "engines": { - "node": ">=14.0" + "node": ">=18.17" } }, "node_modules/undici-types": { @@ -15970,9 +16009,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, "license": "MIT", "engines": { @@ -15980,9 +16019,9 @@ } }, "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, "license": "MIT", "engines": { @@ -16010,9 +16049,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -16757,9 +16796,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", diff --git a/package.json b/package.json index cef0aeb..48be2f7 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@oceanprotocol/contracts": "^2.5.0", "@oceanprotocol/ddo-js": "^0.1.4", "@oceanprotocol/lib": "^6.0.0", + "axios": "^1.11.0", "commander": "^13.1.0", "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", diff --git a/src/cli.ts b/src/cli.ts index 833e9b9..2ee8c77 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -139,11 +139,14 @@ export async function createCLI() { .description("Downloads an asset into specified folder") .argument("", "The asset DID") .argument("[folder]", "Destination folder", ".") + .argument("[serviceId]", "Service ID (optional)") .option("-d, --did ", "The asset DID") .option("-f, --folder [folder]", "Destination folder", ".") - .action(async (did, folder, options) => { + .option("-s, --service ", "Service ID") + .action(async (did, folder, serviceId, options) => { const assetDid = options.did || did; - const destFolder = options.folder || folder || "."; + const destFolder = options.folder || folder || '.'; + const svcId = options.service || serviceId; if (!assetDid) { console.error(chalk.red("DID is required")); // process.exit(1); @@ -151,7 +154,7 @@ export async function createCLI() { } const { signer, chainId } = await initializeSigner(); const commands = new Commands(signer, chainId); - await commands.download([null, assetDid, destFolder]); + await commands.download([null, assetDid, destFolder, svcId]); }); // allowAlgo command @@ -180,139 +183,158 @@ export async function createCLI() { program .command("startCompute") .description("Starts a compute job") - .argument( - "", - "Dataset DIDs (comma-separated) OR (empty array for none)" - ) + .argument("", "Dataset DIDs (comma-separated) OR (empty array for none)") .argument("", "Algorithm DID") .argument("", "Compute environment ID") .argument("", "maxJobDuration for compute job") .argument("", "Payment token for compute") .argument("", "Resources of compute environment stringified") - .option( - "-d, --datasets ", - "Dataset DIDs (comma-separated) OR (empty array for none)" - ) + .argument("[serviceIds]", "Service IDs (comma-separated; positional mapping with datasetDIDs)") + .argument("[algoServiceId]", "Algorithm Service ID (optional)") + .option("-d, --datasets ", "Dataset DIDs (comma-separated) OR (empty array for none)") .option("-a, --algo ", "Algorithm DID") .option("-e, --env ", "Compute environment ID") .option("--maxJobDuration ", "Compute maxJobDuration") .option("-t, --token ", "Compute payment token") + .option("-s, --services [serviceIds]", "Service IDs (comma-separated; positional mapping with datasetDIDs)") + .option("-x, --algo-service [algoServiceId]", "Algorithm Service ID (optional)") .option("--resources ", "Compute resources") - .option( - "--accept [boolean]", - "Auto-confirm payment for compute job (true/false)", - toBoolean - ) - .action( - async ( - datasetDids, - algoDid, - computeEnvId, - maxJobDuration, - paymentToken, - resources, - options - ) => { - const dsDids = options.datasets || datasetDids; - const aDid = options.algo || algoDid; - const envId = options.env || computeEnvId; - const jobDuration = options.maxJobDuration || maxJobDuration; - const token = options.token || paymentToken; - const res = options.resources || resources; - if (!dsDids || !aDid || !envId || !jobDuration || !token || !res) { - console.error(chalk.red("Missing required arguments")); - // process.exit(1); - return; - } - const { signer, chainId } = await initializeSigner(); - const commands = new Commands(signer, chainId); + .option("--accept [boolean]", "Auto-confirm payment for compute job (true/false)", toBoolean) + .action(async (datasetDids, algoDid, computeEnvId, maxJobDuration, paymentToken, resources, serviceIds, algoServiceId, options) => { + const dsDids = options.datasets || datasetDids; + const aDid = options.algo || algoDid; + const envId = options.env || computeEnvId; + const jobDuration = options.maxJobDuration || maxJobDuration; + const token = options.token || paymentToken; + const res = options.resources || resources; + const svcIds = options.services ?? serviceIds ?? ''; + const algoSvcId = options.algoService ?? algoServiceId ?? ''; + if (!dsDids || !aDid || !envId || !jobDuration || !token || !res) { + console.error(chalk.red('Missing required arguments')); + // process.exit(1); + return + } - const initArgs = [null, dsDids, aDid, envId, jobDuration, token, res]; - const initResp = await commands.initializeCompute(initArgs); + const dsArr = + dsDids === '[]' + ? [] + : dsDids.split(',').map(s => s.trim()).filter(Boolean); + + const svArr = svcIds + ? svcIds.split(',').map(s => s.trim()).filter(Boolean) + : undefined; + + // Optional check: serviceIds must match length if provided + if (svArr && svArr.length !== dsArr.length) { + console.error( + chalk.red( + `Length mismatch: datasetDids=${dsArr.length} vs serviceIds=${svArr.length}. ` + + 'If serviceIds is provided, it must match datasetDids length (positional 1–1).' + ) + ); + return; + } + const { signer, chainId } = await initializeSigner(); + const commands = new Commands(signer, chainId); - if (!initResp) { - console.error(chalk.red("Initialization failed. Aborting.")); - return; - } + const initArgs = [null, dsDids, aDid, envId, jobDuration, token, res, svcIds, algoSvcId]; + const initResp = await commands.initializeCompute(initArgs); - console.log(chalk.yellow("\n--- Payment Details ---")); - console.log(JSON.stringify(initResp, null, 2)); - const amount = await unitsToAmount( - signer, - initResp.payment.token, - initResp.payment.amount.toString() - ); + if (!initResp) { + console.error(chalk.red("Initialization failed. Aborting.")); + return; + } + + console.log(chalk.yellow("\n--- Payment Details ---")); + console.log(JSON.stringify(initResp, null, 2)); + const amount = await unitsToAmount( + signer, + initResp.payment.token, + initResp.payment.amount.toString() + ); - const proceed = options.accept; - if (!proceed) { - if (!process.stdin.isTTY) { - console.error( - chalk.red( - 'Cannot prompt for confirmation (non-TTY). Use "--accept true" to skip.' - ) - ); - process.exit(1); - } - const rl = createInterface({ input, output }); - const confirmation = await rl.question( - `\nProceed with payment for starting compute job at price ${amount} in tokens from address ${initResp.payment.token}? (y/n): ` + const proceed = options.accept; + if (!proceed) { + if (!process.stdin.isTTY) { + console.error( + chalk.red( + 'Cannot prompt for confirmation (non-TTY). Use "--accept true" to skip.' + ) ); - rl.close(); - if ( - confirmation.toLowerCase() !== "y" && - confirmation.toLowerCase() !== "yes" - ) { - console.log(chalk.red("Compute job canceled by user.")); - return; - } - } else { - console.log(chalk.cyan("Auto-confirm enabled with --yes flag.")); + process.exit(1); } - - const computeArgs = [ - null, - dsDids, - aDid, - envId, - JSON.stringify(initResp), - jobDuration, - token, - res, - ]; - - await commands.computeStart(computeArgs); - console.log(chalk.green("Compute job started successfully.")); + const rl = createInterface({ input, output }); + const confirmation = await rl.question( + `\nProceed with payment for starting compute job at price ${amount} in tokens from address ${initResp.payment.token}? (y/n): ` + ); + rl.close(); + if ( + confirmation.toLowerCase() !== "y" && + confirmation.toLowerCase() !== "yes" + ) { + console.log(chalk.red("Compute job canceled by user.")); + return; + } + } else { + console.log(chalk.cyan("Auto-confirm enabled with --yes flag.")); } + + const computeArgs = [null, dsDids, aDid, envId, JSON.stringify(initResp), jobDuration, token, res, svcIds, algoSvcId]; + + await commands.computeStart(computeArgs); + console.log(chalk.green("Compute job started successfully.")); + } ); // startFreeCompute command program .command("startFreeCompute") .description("Starts a FREE compute job") - .argument( - "", - "Dataset DIDs (comma-separated) OR (empty array for none)" - ) + .argument("", "Dataset DIDs (comma-separated) OR (empty array for none)") .argument("", "Algorithm DID") .argument("", "Compute environment ID") - .option( - "-d, --datasets ", - "Dataset DIDs (comma-separated) OR (empty array for none)" - ) + .argument("[serviceIds]", "Service IDs (comma-separated; positional mapping with datasetDIDs)") + .argument("[algoServiceId]", "Algorithm Service ID (optional)") + .option("-d, --datasets ", "Dataset DIDs (comma-separated) OR (empty array for none)") .option("-a, --algo ", "Algorithm DID") .option("-e, --env ", "Compute environment ID") - .action(async (datasetDids, algoDid, computeEnvId, options) => { + .option("-s, --services [serviceIds]", "Service IDs (comma-separated; positional mapping with datasetDIDs)") + .option("-x, --algo-service [algoServiceId]", "Algorithm Service ID (optional)") + .action(async (datasetDids, algoDid, computeEnvId, serviceIds, algoServiceId, options) => { const dsDids = options.datasets || datasetDids; const aDid = options.algo || algoDid; const envId = options.env || computeEnvId; + const svcIds = options.services ?? serviceIds ?? ''; + const algoSvcId = options.algoService ?? algoServiceId ?? ''; + if (!dsDids || !aDid || !envId) { console.error(chalk.red("Missing required arguments")); // process.exit(1); + return + } + + const dsArr = + dsDids === '[]' + ? [] + : dsDids.split(',').map(s => s.trim()).filter(Boolean); + + const svArr = svcIds + ? svcIds.split(',').map(s => s.trim()).filter(Boolean) + : undefined; + + // Optional check: serviceIds must match length if provided + if (svArr && svArr.length !== dsArr.length) { + console.error( + chalk.red( + `Length mismatch: datasetDids=${dsArr.length} vs serviceIds=${svArr.length}. ` + + 'If serviceIds is provided, it must match datasetDids length (positional 1–1).' + ) + ); return; } const { signer, chainId } = await initializeSigner(); const commands = new Commands(signer, chainId); - await commands.freeComputeStart([null, dsDids, aDid, envId]); + await commands.freeComputeStart([null, dsDids, aDid, envId, svcIds, algoSvcId]); }); // getComputeEnvironments command @@ -371,7 +393,7 @@ export async function createCLI() { .description("Displays the compute job status") .argument("", "Dataset DID") .argument("", "Job ID") - .argument("", "Agreement ID") + .argument("[agreementId]", "Agreement ID") .option("-d, --dataset ", "Dataset DID") .option("-j, --job ", "Job ID") .option("-a, --agreement [agreementId]", "Agreement ID") diff --git a/src/commands.ts b/src/commands.ts index 165624b..3cd728d 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -1,1780 +1,1934 @@ import fs from "fs"; import util from "util"; import { - createAssetUtil, - handleComputeOrder, - updateAssetMetadata, - downloadFile, - isOrderable, - getMetadataURI, - getIndexingWaitSettings, - IndexerWaitParams, - fixAndParseProviderFees, - getConfigByChainId, + createAssetUtil, + handleComputeOrder, + updateAssetMetadata, + downloadFile, + isOrderable, + getMetadataURI, + getIndexingWaitSettings, + IndexerWaitParams, + fixAndParseProviderFees, + getConfigByChainId, } from "./helpers.js"; import { - Aquarius, - ComputeAlgorithm, - ComputeJob, - ComputeOutput, - Config, - ConfigHelper, - Datatoken, - ProviderInstance, - amountToUnits, - getHash, - orderAsset, - sendTx, - unitsToAmount, - EscrowContract, - getTokenDecimals, - AccesslistFactory, - AccessListContract, + Aquarius, + ComputeAlgorithm, + ComputeJob, + ComputeOutput, + Config, + ConfigHelper, + Datatoken, + ProviderInstance, + amountToUnits, + getHash, + orderAsset, + sendTx, + unitsToAmount, + EscrowContract, + getTokenDecimals, + AccesslistFactory, + AccessListContract, } from "@oceanprotocol/lib"; -import { Asset } from "@oceanprotocol/ddo-js"; +import { Asset, DDOManager } from '@oceanprotocol/ddo-js'; import { Signer, ethers, getAddress } from "ethers"; import { interactiveFlow } from "./interactiveFlow.js"; import { publishAsset } from "./publishAsset.js"; -import chalk from "chalk"; +import chalk from 'chalk'; +import { getPolicyServerOBJ, getPolicyServerOBJs } from "./policyServerHelper.js"; export class Commands { - public signer: Signer; - public config: Config; - public aquarius: Aquarius; - public oceanNodeUrl: string; - // optional settings for indexing wait time - private indexingParams: IndexerWaitParams; - - constructor(signer: Signer, network: string | number, config?: Config) { - this.signer = signer; - this.config = config || new ConfigHelper().getConfig(network); - this.oceanNodeUrl = process.env.NODE_URL; - this.indexingParams = getIndexingWaitSettings(); - console.log("Using Ocean Node URL :", this.oceanNodeUrl); - this.config.nodeUri = this.oceanNodeUrl; - this.aquarius = new Aquarius(this.oceanNodeUrl); - } - - public async start() { - console.log("Starting the interactive CLI flow...\n\n"); - const data = await interactiveFlow(this.oceanNodeUrl); // Collect data via CLI - await publishAsset(this.aquarius, data, this.signer, this.config); // Publish asset with collected data - } - - // utils - public async sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - } - - // commands - public async publish(args: string[]) { - console.log("start publishing"); - let asset; - try { - asset = JSON.parse(fs.readFileSync(args[1], "utf8")); - } catch (e) { - console.error("Cannot read metadata from " + args[1]); - console.error(e); - return; - } - const encryptDDO = args[2] === "false" ? false : true; - try { - // add some more checks - const urlAssetId = await createAssetUtil( - asset.indexedMetadata.nft.name, - asset.indexedMetadata.nft.symbol, - this.signer, - asset.services[0].files, - asset, - this.oceanNodeUrl, - this.config, - this.aquarius, - encryptDDO - ); - console.log("Asset published. ID: " + urlAssetId); - } catch (e) { - console.error("Error when publishing dataset from file: " + args[1]); - console.error(e); - return; - } - } - - public async publishAlgo(args: string[]) { - let algoAsset: Asset; - try { - algoAsset = JSON.parse(fs.readFileSync(args[1], "utf8")); - } catch (e) { - console.error("Cannot read metadata from " + args[1]); - console.error(e); - return; - } - const encryptDDO = args[2] === "false" ? false : true; - // add some more checks - try { - const algoDid = await createAssetUtil( - algoAsset.indexedMetadata.nft.name, - algoAsset.indexedMetadata.nft.symbol, - this.signer, - algoAsset.services[0].files, - algoAsset, - this.oceanNodeUrl, - this.config, - this.aquarius, - encryptDDO - ); - // add some more checks - console.log("Algorithm published. DID: " + algoDid); - } catch (e) { - console.error("Error when publishing dataset from file: " + args[1]); - console.error(e); - return; - } - } - - public async editAsset(args: string[]) { - const asset = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!asset) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - const encryptDDO = args[3] === "false" ? false : true; - let updateJson; - try { - updateJson = JSON.parse(fs.readFileSync(args[2], "utf8")); - } catch (e) { - console.error("Cannot read metadata from " + args[2]); - console.error(e); - return; - } - // Get keys and values - const keys = Object.keys(updateJson); - - for (const key of keys) { - asset[key] = updateJson[key]; - } - - const updateAssetTx = await updateAssetMetadata( - this.signer, - asset, - this.oceanNodeUrl, - this.aquarius, - encryptDDO - ); - console.log("Asset updated. Tx: " + JSON.stringify(updateAssetTx, null, 2)); - } - - public async getDDO(args: string[]) { - console.log("Resolving Asset with DID: " + args[1]); - const resolvedDDO = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!resolvedDDO) { - console.error( - "Error fetching Asset with DID: " + - args[1] + - ". Does this asset exists?" - ); - } else console.log(util.inspect(resolvedDDO, false, null, true)); - } - - public async download(args: string[]) { - const dataDdo = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!dataDdo) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - - const datatoken = new Datatoken( - this.signer, - this.config.chainId, - this.config - ); - - const tx = await orderAsset( - dataDdo, - this.signer, - this.config, - datatoken, - this.oceanNodeUrl - ); - - if (!tx) { - console.error( - "Error ordering access for " + args[1] + ". Do you have enough tokens?" - ); - return; - } - - const orderTx = await tx.wait(); - - const urlDownloadUrl = await ProviderInstance.getDownloadUrl( - dataDdo.id, - dataDdo.services[0].id, - 0, - orderTx.hash, - this.oceanNodeUrl, - this.signer - ); - try { - const path = args[2] ? args[2] : "."; - const { filename } = await downloadFile(urlDownloadUrl, path); - console.log("File downloaded successfully:", path + "/" + filename); - } catch (e) { - console.log(`Download url dataset failed: ${e}`); - } - } - - public async initializeCompute(args: string[]) { - const inputDatasetsString = args[1]; - let inputDatasets = []; - - if ( - inputDatasetsString.includes("[") && - inputDatasetsString.includes("]") - ) { - const processedInput = inputDatasetsString - .replaceAll("]", "") - .replaceAll("[", ""); - if (processedInput.indexOf(",") > -1) { - inputDatasets = processedInput.split(","); - } - } else { - inputDatasets.push(inputDatasetsString); - } - - const ddos = []; - - for (const dataset in inputDatasets) { - const dataDdo = await this.aquarius.waitForIndexer( - inputDatasets[dataset], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!dataDdo) { - console.error( - "Error fetching DDO " + dataset[1] + ". Does this asset exists?" - ); - return; - } else { - ddos.push(dataDdo); - } - } - if ( - inputDatasets.length > 0 && - (ddos.length <= 0 || ddos.length != inputDatasets.length) - ) { - console.error("Not all the data ddos are available."); - return; - } - let providerURI = this.oceanNodeUrl; - if (ddos.length > 0) { - providerURI = ddos[0].services[0].serviceEndpoint; - } - - const algoDdo = await this.aquarius.waitForIndexer( - args[2], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!algoDdo) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - - const computeEnvs = await ProviderInstance.getComputeEnvironments( - this.oceanNodeUrl - ); - - if (!computeEnvs || computeEnvs.length < 1) { - console.error( - "Error fetching compute environments. No compute environments available." - ); - return; - } - - const computeEnvID = args[3]; - // NO chainId needed anymore (is not part of ComputeEnvironment spec anymore) - // const chainComputeEnvs = computeEnvs[computeEnvID]; // was algoDdo.chainId - let computeEnv = null; // chainComputeEnvs[0]; - - if (computeEnvID && computeEnvID.length > 1) { - for (const index in computeEnvs) { - if (computeEnvID == computeEnvs[index].id) { - computeEnv = computeEnvs[index]; - break; - } - } - } - if (!computeEnv || !computeEnvID) { - console.error( - "Error fetching compute environment. No compute environment matches id: ", - computeEnvID - ); - return; - } - - const algo: ComputeAlgorithm = { - documentId: algoDdo.id, - serviceId: algoDdo.services[0].id, - meta: algoDdo.metadata.algorithm, - }; - - const assets = []; - for (const dataDdo in ddos) { - const canStartCompute = isOrderable( - ddos[dataDdo], - ddos[dataDdo].services[0].id, - algo, - algoDdo - ); - if (!canStartCompute) { - console.error( - "Error Cannot start compute job using the datasets DIDs & algorithm DID provided" - ); - return; - } - assets.push({ - documentId: ddos[dataDdo].id, - serviceId: ddos[dataDdo].services[0].id, - }); - } - const maxJobDuration = Number(args[4]); - if (!maxJobDuration) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because maxJobDuration was not provided." - ); - return; - } - if (maxJobDuration < 0) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because maxJobDuration is less than 0. It should be in seconds." - ); - return; - } - let supportedMaxJobDuration: number = maxJobDuration; - if (maxJobDuration > computeEnv.maxJobDuration) { - supportedMaxJobDuration = computeEnv.maxJobDuration; - } - const paymentToken = args[5]; - if (!paymentToken) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because paymentToken was not provided." - ); - return; - } - const { chainId } = await this.signer.provider.getNetwork(); - if (!Object.keys(computeEnv.fees).includes(chainId.toString())) { - console.error( - "Error starting paid compute using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because chainId is not supported by compute environment. " + - args[3] + - ". Supported chain IDs: " + - computeEnv.fees.keys() - ); - return; - } - let found: boolean = false; - for (const fee of computeEnv.fees[chainId.toString()]) { - if (fee.feeToken.toLowerCase() === paymentToken.toLowerCase()) { - found = true; - break; - } - } - if (found === false) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because paymentToken is not supported by this environment " + - args[3] - ); - return; - } - const resources = args[6]; // resources object should be stringified in cli when calling initializeCompute - if (!resources) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because resources for compute were not provided." - ); - return; - } - const parsedResources = JSON.parse(resources); - const providerInitializeComputeJob = - await ProviderInstance.initializeCompute( - assets, - algo, - computeEnv.id, - paymentToken, - supportedMaxJobDuration, - providerURI, - this.signer, // V1 was this.signer.getAddress() - parsedResources, - Number(chainId) - ); - if ( - !providerInitializeComputeJob || - "error" in providerInitializeComputeJob.algorithm - ) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] - ); - return; - } - console.log(chalk.yellow("\n--- Payment Details ---")); - console.log(JSON.stringify(providerInitializeComputeJob, null, 2)); - return providerInitializeComputeJob; - } - - public async computeStart(args: string[]) { - const inputDatasetsString = args[1]; - let inputDatasets = []; - - if ( - inputDatasetsString.includes("[") && - inputDatasetsString.includes("]") - ) { - const processedInput = inputDatasetsString - .replaceAll("]", "") - .replaceAll("[", ""); - if (processedInput.indexOf(",") > -1) { - inputDatasets = processedInput.split(","); - } - } else { - inputDatasets.push(inputDatasetsString); - } - - const ddos = []; - - for (const dataset in inputDatasets) { - const dataDdo = await this.aquarius.waitForIndexer( - inputDatasets[dataset], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!dataDdo) { - console.error( - "Error fetching DDO " + dataset[1] + ". Does this asset exists?" - ); - return; - } else { - ddos.push(dataDdo); - } - } - if ( - inputDatasets.length > 0 && - (ddos.length <= 0 || ddos.length != inputDatasets.length) - ) { - console.error("Not all the data ddos are available."); - return; - } - let providerURI = this.oceanNodeUrl; - if (ddos.length > 0) { - providerURI = ddos[0].services[0].serviceEndpoint; - } - const algoDdo = await this.aquarius.waitForIndexer( - args[2], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!algoDdo) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - - const computeEnvs = await ProviderInstance.getComputeEnvironments( - this.oceanNodeUrl - ); - - if (!computeEnvs || computeEnvs.length < 1) { - console.error( - "Error fetching compute environments. No compute environments available." - ); - return; - } - const computeEnvID = args[3]; - // NO chainId needed anymore (is not part of ComputeEnvironment spec anymore) - // const chainComputeEnvs = computeEnvs[computeEnvID]; // was algoDdo.chainId - let computeEnv = null; // chainComputeEnvs[0]; - - if (computeEnvID && computeEnvID.length > 1) { - for (const index in computeEnvs) { - if (computeEnvID == computeEnvs[index].id) { - computeEnv = computeEnvs[index]; - break; - } - } - } - if (!computeEnv || !computeEnvID) { - console.error( - "Error fetching compute environment. No compute environment matches id: ", - computeEnvID - ); - return; - } - - const algo: ComputeAlgorithm = { - documentId: algoDdo.id, - serviceId: algoDdo.services[0].id, - meta: algoDdo.metadata.algorithm, - }; - - const assets = []; - for (const dataDdo in ddos) { - const canStartCompute = isOrderable( - ddos[dataDdo], - ddos[dataDdo].services[0].id, - algo, - algoDdo - ); - if (!canStartCompute) { - console.error( - "Error Cannot start compute job using the datasets DIDs & algorithm DID provided" - ); - return; - } - assets.push({ - documentId: ddos[dataDdo].id, - serviceId: ddos[dataDdo].services[0].id, - }); - } - const providerInitializeComputeJob = args[4]; // provider fees + payment - const parsedProviderInitializeComputeJob = fixAndParseProviderFees( - providerInitializeComputeJob - ); - console.log("Ordering algorithm: ", args[2]); - const datatoken = new Datatoken( - this.signer, - (await this.signer.provider.getNetwork()).chainId.toString(), - this.config - ); - algo.transferTxId = await handleComputeOrder( - parsedProviderInitializeComputeJob?.algorithm, - algoDdo, - this.signer, - computeEnv.consumerAddress, - 0, - datatoken, - this.config, - parsedProviderInitializeComputeJob?.algorithm?.providerFee, - providerURI - ); - if (!algo.transferTxId) { - console.error( - "Error ordering compute for algorithm with DID: " + - args[2] + - ". Do you have enough tokens?" - ); - return; - } - console.log("Ordering assets: ", args[1]); - - for (let i = 0; i < ddos.length; i++) { - assets[i].transferTxId = await handleComputeOrder( - parsedProviderInitializeComputeJob?.datasets[i], - ddos[i], - this.signer, - computeEnv.consumerAddress, - 0, - datatoken, - this.config, - parsedProviderInitializeComputeJob?.datasets[i].providerFee, - providerURI - ); - if (!assets[i].transferTxId) { - console.error( - "Error ordering dataset with DID: " + - assets[i] + - ". Do you have enough tokens?" - ); - return; - } - } - // payment check - const maxJobDuration = Number(args[5]); - if (!maxJobDuration) { - console.error( - "Error initializing Provider for the compute job using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because maxJobDuration was not provided." - ); - return; - } - if (maxJobDuration < 0) { - console.error( - "Error starting paid compute using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because maxJobDuration is less than 0. It should be in seconds." - ); - return; - } - let supportedMaxJobDuration: number = maxJobDuration; - if (maxJobDuration > computeEnv.maxJobDuration) { - supportedMaxJobDuration = computeEnv.maxJobDuration; - } - const { chainId } = await this.signer.provider.getNetwork(); - const paymentToken = args[6]; - if (!paymentToken) { - console.error( - "Error starting paid compute using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because paymentToken was not provided." - ); - return; - } - if (!Object.keys(computeEnv.fees).includes(chainId.toString())) { - console.error( - "Error starting paid compute using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because chainId is not supported by compute environment. " + - args[3] + - ". Supported chain IDs: " + - computeEnv.fees.keys() - ); - return; - } - let found: boolean = false; - for (const fee of computeEnv.fees[chainId.toString()]) { - if (fee.feeToken.toLowerCase() === paymentToken.toLowerCase()) { - found = true; - break; - } - } - if (found === false) { - console.error( - "Error starting paid compute using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because paymentToken is not supported by this environment " + - args[3] - ); - return; - } - const resources = args[7]; // resources object should be stringified in cli when calling initializeCompute - if (!resources) { - console.error( - "Error starting paid compute using dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because resources for compute were not provided." - ); - return; - } - - const escrow = new EscrowContract( - getAddress(parsedProviderInitializeComputeJob.payment.escrowAddress), - this.signer - ); - console.log("Verifying payment..."); - await new Promise((resolve) => setTimeout(resolve, 3000)); - - const validationEscrow = await escrow.verifyFundsForEscrowPayment( - paymentToken, - computeEnv.consumerAddress, - await unitsToAmount( - this.signer, - paymentToken, - parsedProviderInitializeComputeJob.payment.amount - ), - parsedProviderInitializeComputeJob.payment.amount.toString(), - parsedProviderInitializeComputeJob.payment.minLockSeconds.toString(), - "10" - ); - if (validationEscrow.isValid === false) { - console.error( - "Error starting compute job dataset DID " + - args[1] + - " and algorithm DID " + - args[2] + - " because escrow funds check failed: " + - validationEscrow.message - ); - return; - } - - console.log("Starting compute job using provider: ", providerURI); - - const additionalDatasets = assets.length > 1 ? assets.slice(1) : null; - if (assets.length > 0) { - console.log( - "Starting compute job on " + - assets[0].documentId + - " with additional datasets:" + - (!additionalDatasets ? "none" : additionalDatasets[0].documentId) - ); - } else { - console.log( - "Starting compute job on " + - algo.documentId + - " with additional datasets:" + - (!additionalDatasets ? "none" : additionalDatasets[0].documentId) - ); - } - if (additionalDatasets !== null) { - console.log( - "Adding additional datasets to dataset, according to C2D V2 specs" - ); - assets.push(additionalDatasets); - } - - const output: ComputeOutput = { - metadataUri: await getMetadataURI(), - }; - - const computeJobs = await ProviderInstance.computeStart( - providerURI, - this.signer, - computeEnv.id, - assets, // assets[0] // only c2d v1, - algo, - supportedMaxJobDuration, - paymentToken, - JSON.parse(resources), - Number((await this.signer.provider.getNetwork()).chainId), - null, - null, - // additionalDatasets, only c2d v1 - output - ); - - console.log("computeJobs: ", computeJobs); - - if (computeJobs && computeJobs[0]) { - const { jobId, payment } = computeJobs[0]; - console.log("Compute started. JobID: " + jobId); - console.log("Agreement ID: " + payment.lockTx); - } else { - console.log("Error while starting the compute job: ", computeJobs); - } - } - - public async freeComputeStart(args: string[]) { - const inputDatasetsString = args[1]; - let inputDatasets = []; - - if ( - inputDatasetsString.includes("[") && - inputDatasetsString.includes("]") - ) { - const processedInput = inputDatasetsString - .replaceAll("]", "") - .replaceAll("[", ""); - if (processedInput.indexOf(",") > -1) { - inputDatasets = processedInput.split(","); - } - } else { - inputDatasets.push(inputDatasetsString); - } - - const ddos = []; - - for (const dataset in inputDatasets) { - const dataDdo = await this.aquarius.waitForIndexer( - inputDatasets[dataset], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!dataDdo) { - console.error( - "Error fetching DDO " + dataset[1] + ". Does this asset exists?" - ); - return; - } else { - ddos.push(dataDdo); - } - } - - if ( - inputDatasets.length > 0 && - (ddos.length <= 0 || ddos.length != inputDatasets.length) - ) { - console.error("Not all the data ddos are available."); - return; - } - let providerURI = this.oceanNodeUrl; - if (ddos.length > 0) { - providerURI = ddos[0].services[0].serviceEndpoint; - } - - const algoDdo = await this.aquarius.waitForIndexer( - args[2], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!algoDdo) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - - const computeEnvs = await ProviderInstance.getComputeEnvironments( - this.oceanNodeUrl - ); - - if (!computeEnvs || computeEnvs.length < 1) { - console.error( - "Error fetching compute environments. No compute environments available." - ); - return; - } - - const mytime = new Date(); - const computeMinutes = 5; - mytime.setMinutes(mytime.getMinutes() + computeMinutes); - - const computeEnvID = args[3]; - // NO chainId needed anymore (is not part of ComputeEnvironment spec anymore) - // const chainComputeEnvs = computeEnvs[computeEnvID]; // was algoDdo.chainId - let computeEnv = null; // chainComputeEnvs[0]; - - if (computeEnvID && computeEnvID.length > 1) { - for (const env of computeEnvs) { - if (computeEnvID == env.id && env.free) { - computeEnv = env; - break; - } - } - } - - if (!computeEnv || !computeEnvID) { - console.error( - "Error fetching free compute environment. No free compute environment matches id: ", - computeEnvID - ); - return; - } - - const algo: ComputeAlgorithm = { - documentId: algoDdo.id, - serviceId: algoDdo.services[0].id, - meta: algoDdo.metadata.algorithm, - }; - - const assets = []; - for (const dataDdo in ddos) { - const canStartCompute = isOrderable( - ddos[dataDdo], - ddos[dataDdo].services[0].id, - algo, - algoDdo - ); - if (!canStartCompute) { - console.error( - "Error Cannot start compute job using the datasets DIDs & algorithm DID provided" - ); - return; - } - assets.push({ - documentId: ddos[dataDdo].id, - serviceId: ddos[dataDdo].services[0].id, - }); - } - - console.log("Starting compute job using provider: ", providerURI); - const additionalDatasets = assets.length > 1 ? assets.slice(1) : null; - if (assets.length > 0) { - console.log( - "Starting compute job on " + - assets[0].documentId + - " with additional datasets:" + - (!additionalDatasets ? "none" : additionalDatasets[0].documentId) - ); - } else { - console.log( - "Starting compute job on " + - algo.documentId + - " with additional datasets:" + - (!additionalDatasets ? "none" : additionalDatasets[0].documentId) - ); - } - - if (additionalDatasets !== null) { - console.log( - "Adding additional datasets to dataset, according to C2D V2 specs" - ); - assets.push(additionalDatasets); - } - - const output: ComputeOutput = { - metadataUri: await getMetadataURI(), - }; - - const computeJobs = await ProviderInstance.freeComputeStart( - providerURI, - this.signer, - computeEnv.id, - assets, // assets[0] // only c2d v1, - algo, - null, - null, - null, - output - ); - - console.log("compute jobs: ", computeJobs); - - if (computeJobs && computeJobs[0]) { - const { jobId } = computeJobs[0]; - console.log("Compute started. JobID: " + jobId); - } else { - console.log("Error while starting the compute job: ", computeJobs); - } - } - - public async computeStop(args: string[]) { - const dataDdo = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!dataDdo) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - - const jobId = args[2]; - const jobStatus = await ProviderInstance.computeStop( - jobId, - this.oceanNodeUrl, - this.signer - ); - console.log(jobStatus); - } - - public async getComputeEnvironments() { - const computeEnvs = await ProviderInstance.getComputeEnvironments( - this.oceanNodeUrl - ); - - if (!computeEnvs || computeEnvs.length < 1) { - console.error( - "Error fetching compute environments. No compute environments available." - ); - return; - } - - console.log("Exiting compute environments: ", JSON.stringify(computeEnvs)); - } - - public async computeStreamableLogs(args: string[]) { - const jobId = args[0]; - const logsResponse = await ProviderInstance.computeStreamableLogs( - this.oceanNodeUrl, - this.signer, - jobId - ); - console.log("response: ", logsResponse); - - if (!logsResponse) { - console.error("Error fetching streamable logs. No logs available."); - return; - } else { - const stream = logsResponse as ReadableStream; - console.log("stream: ", stream); - const text = await new Response(stream).text(); - console.log("Streamable Logs: "); - console.log(text); - // for await (const value of stream) { - // // just print it to the console - // console.log(value); - // } - } - console.log("Exiting computeStreamableLogs: ", logsResponse); - } - - public async allowAlgo(args: string[]) { - const asset = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!asset) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - - if (asset.indexedMetadata.nft.owner !== (await this.signer.getAddress())) { - console.error( - "You are not the owner of this asset, and there for you cannot update it." - ); - return; - } - - if (asset.services[0].type !== "compute") { - console.error( - "Error getting computeService for " + - args[1] + - ". Does this asset has an computeService?" - ); - return; - } - const algoAsset = await this.aquarius.waitForIndexer( - args[2], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!algoAsset) { - console.error( - "Error fetching DDO " + args[2] + ". Does this asset exists?" - ); - return; - } - const encryptDDO = args[3] === "false" ? false : true; - let filesChecksum; - try { - filesChecksum = await ProviderInstance.checkDidFiles( - algoAsset.id, - algoAsset.services[0].id, - algoAsset.services[0].serviceEndpoint, - true - ); - } catch (e) { - console.error("Error checking algo files: ", e); - return; - } - - const containerChecksum = - algoAsset.metadata.algorithm.container.entrypoint + - algoAsset.metadata.algorithm.container.checksum; - const trustedAlgorithm = { - did: algoAsset.id, - containerSectionChecksum: getHash(containerChecksum), - filesChecksum: filesChecksum?.[0]?.checksum, - }; - asset.services[0].compute.publisherTrustedAlgorithms.push(trustedAlgorithm); - try { - const txid = await updateAssetMetadata( - this.signer, - asset, - this.oceanNodeUrl, - this.aquarius, - encryptDDO - ); - console.log("Successfully updated asset metadata: " + txid); - } catch (e) { - console.error("Error updating asset metadata: ", e); - return; - } - } - - public async disallowAlgo(args: string[]) { - const asset = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!asset) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - if (asset.indexedMetadata.nft.owner !== (await this.signer.getAddress())) { - console.error( - "You are not the owner of this asset, and there for you cannot update it." - ); - return; - } - if (asset.services[0].type !== "compute") { - console.error( - "Error getting computeService for " + - args[1] + - ". Does this asset has an computeService?" - ); - return; - } - if (asset.services[0].compute.publisherTrustedAlgorithms) { - console.error( - " " + args[1] + ". Does this asset has an computeService?" - ); - return; - } - const encryptDDO = args[3] === "false" ? false : true; - const indexToDelete = - asset.services[0].compute.publisherTrustedAlgorithms.findIndex( - (item) => item.did === args[2] - ); - - if (indexToDelete !== -1) { - asset.services[0].compute.publisherTrustedAlgorithms.splice( - indexToDelete, - 1 - ); - } else { - console.error( - " " + - args[2] + - ". is not allowed by the publisher to run on " + - args[1] - ); - return; - } - - const txid = await updateAssetMetadata( - this.signer, - asset, - this.oceanNodeUrl, - this.aquarius, - encryptDDO - ); - console.log("Asset updated " + txid); - } - - public async getJobStatus(args: string[]) { - // args[1] - did (for checking if data asset exists, legacy) - // args[2] - jobId - // args[3] - agreementId - const hasAgreementId = args.length === 4; - - const dataDdo = await this.aquarius.waitForIndexer( - args[1], - null, - null, - this.indexingParams.retryInterval, - this.indexingParams.maxRetries - ); - if (!dataDdo) { - console.error( - "Error fetching DDO " + args[1] + ". Does this asset exists?" - ); - return; - } - const jobId = args[2]; - let agreementId = null; - if (hasAgreementId) { - agreementId = args[3]; - } - - const jobStatus = (await ProviderInstance.computeStatus( - this.oceanNodeUrl, - await this.signer.getAddress(), - jobId, - agreementId - )) as ComputeJob; - console.log(util.inspect(jobStatus, false, null, true)); - } - - public async downloadJobResults(args: string[]) { - const jobResult = await ProviderInstance.getComputeResultUrl( - this.oceanNodeUrl, - this.signer, - args[1], - parseInt(args[2]) - ); - console.log("jobResult ", jobResult); - - try { - const path = args[3] ? args[3] : "."; - const { filename } = await downloadFile( - jobResult, - path, - parseInt(args[2]) - ); - console.log("File downloaded successfully:", path + "/" + filename); - } catch (e) { - console.log(`Download url dataset failed: ${e}`); - } - } - - public async mintOceanTokens() { - try { - const config = await getConfigByChainId(Number(this.config.chainId)); - const minAbi = [ - { - constant: false, - inputs: [ - { name: "to", type: "address" }, - { name: "value", type: "uint256" }, - ], - name: "mint", - outputs: [{ name: "", type: "bool" }], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - ]; - - const tokenContract = new ethers.Contract( - config?.Ocean, - minAbi, - this.signer - ); - const estGasPublisher = await tokenContract.mint.estimateGas( - await this.signer.getAddress(), - await amountToUnits(null, null, "1000", 18) - ); - const tx = await sendTx( - estGasPublisher, - this.signer, - 1, - tokenContract.mint, - await this.signer.getAddress(), - amountToUnits(null, null, "1000", 18) - ); - await tx.wait(); - } catch (error) { - console.error("Error minting Ocean tokens:", error); - } - } - - public async generateAuthToken() { - const authToken = await ProviderInstance.generateAuthToken( - this.signer, - this.oceanNodeUrl - ); - console.log(`Auth token successfully generated: ${authToken}`); - } - - public async invalidateAuthToken(args: string[]) { - const authToken = args[0]; - const result = await ProviderInstance.invalidateAuthToken( - this.signer, - authToken, - this.oceanNodeUrl - ); - if (!result.success) { - console.log("Auth token could not be invalidated"); - return; - } - - console.log(`Auth token successfully invalidated`); - } - - public async getEscrowBalance(token: string): Promise { - const config = await getConfigByChainId(Number(this.config.chainId)); - const escrow = new EscrowContract( - getAddress(config.Escrow), - this.signer, - Number(this.config.chainId) - ); - - try { - const balance = await escrow.getUserFunds( - await this.signer.getAddress(), - token - ); - const decimals = await getTokenDecimals(this.signer, token); - const available = balance.available; - const amount = await unitsToAmount( - this.signer, - token, - available, - decimals - ); - console.log(`Escrow user funds for token ${token}: ${amount}`); - return Number(amount); - } catch (error) { - console.error("Error getting escrow balance:", error); - } - } - - public async withdrawFromEscrow( - token: string, - amount: string - ): Promise { - const config = await getConfigByChainId(Number(this.config.chainId)); - const escrow = new EscrowContract( - getAddress(config.Escrow), - this.signer, - Number(this.config.chainId) - ); - - const balance = await this.getEscrowBalance(token); - if (balance < Number(amount)) { - console.error(`Insufficient balance in escrow for token ${token}`); - return; - } - - const withdrawTx = await escrow.withdraw([token], [amount]); - await withdrawTx.wait(); - console.log(`Successfully withdrawn ${amount} ${token} from escrow`); - } - - public async depositToEscrow( - signer: Signer, - token: string, - amount: string, - chainId: number - ) { - try { - const amountInUnits = await amountToUnits(signer, token, amount, 18); - const config = await getConfigByChainId(chainId); - const escrowAddress = config.Escrow; - - const tokenContract = new ethers.Contract( - token, - ["function approve(address spender, uint256 amount) returns (bool)"], - signer - ); - - const escrow = new EscrowContract( - getAddress(escrowAddress), - signer, - chainId - ); - - console.log("Approving token transfer..."); - const approveTx = await tokenContract.approve( - escrowAddress, - amountInUnits - ); - await approveTx.wait(); - console.log(`Successfully approved ${amount} ${token} to escrow`); - - console.log("Depositing to escrow..."); - const depositTx = await escrow.deposit(token, amount); - await depositTx.wait(); - return true; - } catch (error) { - console.error("Error depositing to escrow:", error); - return false; - } - } - - public async authorizeEscrowPayee( - token: string, - payee: string, - maxLockedAmount: string, - maxLockSeconds: string, - maxLockCounts: string - ) { - try { - const config = await getConfigByChainId(Number(this.config.chainId)); - const escrowAddress = config.Escrow; - - const escrow = new EscrowContract(getAddress(escrowAddress), this.signer); - - console.log("Authorizing payee..."); - const authorizeTx = await escrow.authorize( - getAddress(token), - getAddress(payee), - maxLockedAmount, - maxLockSeconds, - maxLockCounts - ); - await authorizeTx.wait(); - console.log(`Successfully authorized payee ${payee} for token ${token}`); - - return true; - } catch (error) { - console.error("Error authorizing payee:", error); - return false; - } - } - - public async getAuthorizationsEscrow(token: string, payee: string) { - const config = await getConfigByChainId(Number(this.config.chainId)); - const payer = await this.signer.getAddress(); - const tokenAddress = getAddress(token); - const payerAddress = getAddress(payer); - const payeeAddress = getAddress(payee); - const decimals = await getTokenDecimals(this.signer, token); - const escrow = new EscrowContract( - getAddress(config.Escrow), - this.signer, - Number(this.config.chainId) - ); - - const authorizations = await escrow.getAuthorizations( - tokenAddress, - payerAddress, - payeeAddress - ); - const authorization = authorizations[0]; - if (!authorization || authorization.length === 0) { - console.log("No authorizations found"); - return; - } - - const currentLockedAmount = await unitsToAmount( - this.signer, - token, - authorization.currentLockedAmount.toString(), - decimals - ); - const maxLockedAmount = await unitsToAmount( - this.signer, - token, - authorization.maxLockedAmount.toString(), - decimals - ); - - console.log("Authorizations found:"); - console.log(`- Current Locked Amount: ${Number(currentLockedAmount)}`); - console.log(`- Current Locks: ${authorization.currentLocks}`); - console.log(`- Max locked amount: ${Number(maxLockedAmount)}`); - console.log(`- Max lock seconds: ${authorization.maxLockSeconds}`); - console.log(`- Max lock counts: ${authorization.maxLockCounts}`); - - return authorizations; - } - - public async createAccessList(args: string[]): Promise { - try { - const name = args[0]; - const symbol = args[1]; - const transferable = args[2] === "true"; - const initialUsers = args[3] - ? args[3].split(",").map((u) => u.trim()) - : []; - - if (!name || !symbol) { - console.error(chalk.red("Name and symbol are required")); - return; - } - - const config = await getConfigByChainId(Number(this.config.chainId)); - if (!config.AccessListFactory) { - console.error( - chalk.red( - "Access list factory not found. Check local address.json file" - ) - ); - return; - } - const accessListFactory = new AccesslistFactory( - config.AccessListFactory, - this.signer, - Number(this.config.chainId) - ); - - const owner = await this.signer.getAddress(); - const tokenURIs = initialUsers.map( - () => "https://oceanprotocol.com/nft/" - ); - - console.log(chalk.cyan("Creating new access list...")); - console.log(`Name: ${name}`); - console.log(`Symbol: ${symbol}`); - console.log(`Transferable: ${transferable}`); - console.log(`Owner: ${owner}`); - console.log( - `Initial users: ${ - initialUsers.length > 0 ? initialUsers.join(", ") : "none" - }` - ); - - const accessListAddress = - await accessListFactory.deployAccessListContract( - name, - symbol, - tokenURIs, - transferable, - owner, - initialUsers - ); - - console.log(chalk.green(`\nAccess list created successfully!`)); - console.log(chalk.green(`Contract address: ${accessListAddress}`)); - } catch (error) { - console.error(chalk.red("Error creating access list:"), error); - } - } - - public async addToAccessList(args: string[]): Promise { - try { - const accessListAddress = args[0]; - const users = args[1].split(",").map((u) => u.trim()); - - if (!accessListAddress || users.length === 0) { - console.error( - chalk.red("Access list address and at least one user are required") - ); - return; - } - - const accessList = new AccessListContract( - accessListAddress, - this.signer, - Number(this.config.chainId) - ); - - console.log( - chalk.cyan(`Adding ${users.length} user(s) to access list...`) - ); - - if (users.length === 1) { - const tx = await accessList.mint( - users[0], - "https://oceanprotocol.com/nft/" - ); - await tx.wait(); - console.log( - chalk.green(`Successfully added user ${users[0]} to access list`) - ); - return; - } - - const tokenURIs = users.map(() => "https://oceanprotocol.com/nft/"); - const tx = await accessList.batchMint(users, tokenURIs); - await tx.wait(); - console.log( - chalk.green(`Successfully added ${users.length} users to access list:`) - ); - users.forEach((user) => console.log(` - ${user}`)); - } catch (error) { - console.error(chalk.red("Error adding users to access list:"), error); - } - } - - public async checkAccessList(args: string[]): Promise { - try { - const accessListAddress = args[0]; - const users = args[1].split(",").map((u) => u.trim()); - - if (!accessListAddress || users.length === 0) { - console.error( - chalk.red("Access list address and at least one user are required") - ); - return; - } - - const accessList = new AccessListContract( - accessListAddress, - this.signer, - Number(this.config.chainId) - ); - - console.log( - chalk.cyan(`Checking access list for ${users.length} user(s)...\n`) - ); - - for (const user of users) { - const balance = await accessList.balance(user); - const hasAccess = Number(balance) > 0; - - if (hasAccess) { - console.log( - chalk.green(`✓ ${user}: Has access (balance: ${balance})`) - ); - } else { - console.log(chalk.red(`✗ ${user}: No access`)); - } - } - } catch (error) { - console.error(chalk.red("Error checking access list:"), error); - } - } - - public async removeFromAccessList(args: string[]): Promise { - try { - const accessListAddress = args[0]; - const users = args[1].split(",").map((u) => u.trim()); - - if (!accessListAddress || users.length === 0) { - console.error( - chalk.red( - "Access list address and at least one user address are required" - ) - ); - return; - } - - const accessList = new AccessListContract( - accessListAddress, - this.signer, - Number(this.config.chainId) - ); - - console.log( - chalk.cyan(`Removing ${users.length} user(s) from access list...`) - ); - for (const user of users) { - const balance = await accessList.balance(user); - - if (Number(balance) === 0) { - console.log( - chalk.yellow( - `⚠ User ${user} is not on the access list, skipping...` - ) - ); - continue; - } - - const balanceNum = Number(balance); - const contract = accessList.contract; - - let removedCount = 0; - for (let index = 0; index < balanceNum; index++) { - try { - const tokenId = await contract.tokenOfOwnerByIndex(user, index); - const tx = await accessList.burn(Number(tokenId)); - await tx.wait(); - - console.log( - chalk.green( - `✓ Successfully removed user ${user} (token ID: ${tokenId})` - ) - ); - removedCount++; - } catch (e: any) { - console.log( - chalk.yellow( - `⚠ Could not remove token at index ${index} for user ${user}: ${e.message}` - ) - ); - } - } - - if (removedCount === 0) { - console.log( - chalk.yellow(`⚠ Could not remove any tokens for user ${user}`) - ); - } else if (removedCount < balanceNum) { - console.log( - chalk.yellow( - `⚠ Only removed ${removedCount} of ${balanceNum} tokens for user ${user}` - ) - ); - } - } - } catch (error) { - console.error(chalk.red("Error removing users from access list:"), error); - } - } - - public async downloadNodeLogs(args: string[]): Promise { - try { - const outputLocation = args[0]; - const last = args[1]; - let from = args[2]; - let to = args[3]; - const maxLogs = args[4] ? Math.min(parseInt(args[4], 10), 1000) : undefined; - - if (!outputLocation) { - console.error(chalk.red("Output location is required")); - return; - } - - if (!fs.existsSync(outputLocation)) { - console.error( - chalk.red(`Output directory does not exist: ${outputLocation}`) - ); - return; - } - - if (last && (from || to)) { - console.error( - chalk.red("Use either --last or --from/--to, not both") - ); - return; - } - - if ((from && !to) || (!from && to)) { - console.error( - chalk.red( - "Both --from and --to are required when specifying a time range" - ) - ); - return; - } - - if (!last && !from && !to) { - to = `${Date.now()}`; - from = `${Date.now() - 60 * 60 * 1000}`; // default: last 1 hour - } - - if (last) { - to = `${Date.now()}`; - from = `${Date.now() - parseInt(last, 10) * 60 * 60 * 1000}`; - } - - const response = await ProviderInstance.downloadNodeLogs( - this.oceanNodeUrl, - this.signer, - from, - to, - maxLogs - ); - - const text = await new Response(response).text(); - const outputPath = `${outputLocation}/logs.json`; - fs.writeFileSync(outputPath, text); - console.log(chalk.green(`Logs saved to ${outputPath}`)); - } catch (error) { - console.error(chalk.red("Error downloading node logs: "), error); - } - } + public signer: Signer; + public config: Config; + public aquarius: Aquarius; + public oceanNodeUrl: string; + // optional settings for indexing wait time + private indexingParams: IndexerWaitParams; + + constructor(signer: Signer, network: string | number, config?: Config) { + this.signer = signer; + this.config = config || new ConfigHelper().getConfig(network); + this.oceanNodeUrl = process.env.NODE_URL; + this.indexingParams = getIndexingWaitSettings(); + console.log("Using Ocean Node URL :", this.oceanNodeUrl); + this.config.nodeUri = this.oceanNodeUrl; + this.aquarius = new Aquarius(this.oceanNodeUrl); + } + + public async start() { + console.log("Starting the interactive CLI flow...\n\n"); + const data = await interactiveFlow(this.oceanNodeUrl); // Collect data via CLI + await publishAsset(this.aquarius, data, this.signer, this.config); // Publish asset with collected data + } + + // utils + public async sleep(ms: number) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + } + + // commands + public async publish(args: string[]) { + console.log("start publishing"); + let asset; + try { + asset = JSON.parse(fs.readFileSync(args[1], "utf8")); + } catch (e) { + console.error("Cannot read metadata from " + args[1]); + console.error(e); + return; + } + const encryptDDO = args[2] === "false" ? false : true; + try { + const ddoInstance = DDOManager.getDDOClass(asset); + const { indexedMetadata } = ddoInstance.getAssetFields(); + const { services } = ddoInstance.getDDOFields(); + // add some more checks + const urlAssetId = await createAssetUtil( + indexedMetadata.nft.name, + indexedMetadata.nft.symbol, + this.signer, + services[0].files, + asset, + this.oceanNodeUrl, + this.config, + this.aquarius, + encryptDDO + ); + console.log("Asset published. ID: " + urlAssetId); + } catch (e) { + console.error("Error when publishing dataset from file: " + args[1]); + console.error(e); + return; + } + } + + public async publishAlgo(args: string[]) { + let algoAsset: Asset; + try { + algoAsset = JSON.parse(fs.readFileSync(args[1], "utf8")); + } catch (e) { + console.error("Cannot read metadata from " + args[1]); + console.error(e); + return; + } + const encryptDDO = args[2] === "false" ? false : true; + // add some more checks + try { + const ddoInstance = DDOManager.getDDOClass(algoAsset); + const { indexedMetadata } = ddoInstance.getAssetFields(); + const { services } = ddoInstance.getDDOFields(); + const algoDid = await createAssetUtil( + indexedMetadata.nft.name, + indexedMetadata.nft.symbol, + this.signer, + services[0].files, + algoAsset, + this.oceanNodeUrl, + this.config, + this.aquarius, + encryptDDO + ); + // add some more checks + console.log("Algorithm published. DID: " + algoDid); + } catch (e) { + console.error("Error when publishing dataset from file: " + args[1]); + console.error(e); + return; + } + } + + public async editAsset(args: string[]) { + const asset = await this.aquarius.waitForIndexer( + args[1], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!asset) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + const encryptDDO = args[3] === "false" ? false : true; + let updateJson; + try { + updateJson = JSON.parse(fs.readFileSync(args[2], "utf8")); + } catch (e) { + console.error("Cannot read metadata from " + args[2]); + console.error(e); + return; + } + // Get keys and values + const keys = Object.keys(updateJson); + + for (const key of keys) { + asset[key] = updateJson[key]; + } + + const updateAssetTx = await updateAssetMetadata( + this.signer, + asset, + this.oceanNodeUrl, + this.aquarius, + encryptDDO + ); + console.log("Asset updated. Tx: " + JSON.stringify(updateAssetTx, null, 2)); + } + + public async getDDO(args: string[]) { + console.log("Resolving Asset with DID: " + args[1]); + const resolvedDDO = await this.aquarius.waitForIndexer( + args[1], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!resolvedDDO) { + console.error( + "Error fetching Asset with DID: " + + args[1] + + ". Does this asset exists?" + ); + } else console.log(util.inspect(resolvedDDO, false, null, true)); + } + + public async download(args: string[]) { + const did = args[1]; + const dataDdo = await this.aquarius.waitForIndexer( + did, + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!dataDdo) { + console.error( + "Error fetching DDO " + did + ". Does this asset exists?" + ); + return; + } + + const ddoInstance = DDOManager.getDDOClass(dataDdo); + const { services, version } = ddoInstance.getDDOFields(); + const serviceId = args[3] ? args[3] : services[0].id; + let policyServer = null + try { + if (version >= '5.0.0') { + policyServer = await getPolicyServerOBJ(dataDdo, serviceId, this.signer, this.oceanNodeUrl); + } + } catch (error) { + throw new Error('Error getting Policy Server Object: ' + error.message) + } + const datatoken = new Datatoken( + this.signer, + this.config.chainId, + this.config + ); + const tx = await orderAsset( + dataDdo, + this.signer, + this.config, + datatoken, + this.oceanNodeUrl + ); + + if (!tx) { + console.error( + "Error ordering access for " + did + ". Do you have enough tokens?" + ); + return; + } + + const orderTx = await tx.wait(); + + const urlDownloadUrl = await ProviderInstance.getDownloadUrl( + dataDdo.id, + serviceId, + 0, + orderTx.hash, + this.oceanNodeUrl, + this.signer, + policyServer + ); + try { + const path = args[2] ? args[2] : "."; + const { filename } = await downloadFile(urlDownloadUrl, path); + console.log("File downloaded successfully:", path + "/" + filename); + } catch (e) { + console.log(`Download url dataset failed: ${e}`); + } + } + + public async initializeCompute(args: string[]) { + const inputDatasetsString = args[1]; + let inputDatasets = []; + + if (!inputDatasetsString || inputDatasetsString.trim() === '[]') { + inputDatasets = []; + } else { + const cleaned = inputDatasetsString.replaceAll('[', '').replaceAll(']', ''); + inputDatasets = cleaned.split(',').map(s => s.trim()).filter(Boolean); + } + + const inputServicesString = args[7]; + let inputServices: string[] = []; + if (typeof inputServicesString === 'string' && inputServicesString.trim().length > 0) { + inputServices = inputServicesString.split(',').map(s => s.trim()).filter(Boolean); + } else if (Array.isArray(inputServicesString)) { + inputServices = inputServicesString.map(String).map(s => s.trim()).filter(Boolean); + } + + const ddos = []; + + for (const dataset in inputDatasets) { + const dataDdo = await this.aquarius.waitForIndexer( + inputDatasets[dataset], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!dataDdo) { + console.error( + "Error fetching DDO " + dataset[1] + ". Does this asset exists?" + ); + return; + } else { + ddos.push(dataDdo); + } + } + if ( + inputDatasets.length > 0 && + (ddos.length <= 0 || ddos.length != inputDatasets.length) + ) { + console.error("Not all the data ddos are available."); + return; + } + let providerURI = this.oceanNodeUrl; + const ddoInstance = DDOManager.getDDOClass(ddos[0]); + const { services } = ddoInstance.getDDOFields(); + if (ddos.length > 0) { + providerURI = services[0].serviceEndpoint; + } + const algoDdo = await this.aquarius.waitForIndexer( + args[2], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!algoDdo) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + + const computeEnvs = await ProviderInstance.getComputeEnvironments( + this.oceanNodeUrl + ); + + if (!computeEnvs || computeEnvs.length < 1) { + console.error( + "Error fetching compute environments. No compute environments available." + ); + return; + } + + const computeEnvID = args[3]; + // NO chainId needed anymore (is not part of ComputeEnvironment spec anymore) + // const chainComputeEnvs = computeEnvs[computeEnvID]; // was algoDdo.chainId + let computeEnv = null; // chainComputeEnvs[0]; + if (computeEnvID && computeEnvID.length > 1) { + for (const index in computeEnvs) { + if (computeEnvID == computeEnvs[index].id) { + computeEnv = computeEnvs[index]; + break; + } + } + } + if (!computeEnv || !computeEnvID) { + console.error( + "Error fetching compute environment. No compute environment matches id: ", + computeEnvID + ); + return; + } + const ddoAlgoInstance = DDOManager.getDDOClass(algoDdo); + const { services: servicesAlgo, metadata: metadataAlgo, version: versionAlgo } = ddoAlgoInstance.getDDOFields(); + const algoServiceIdInput = args[8] as string | undefined; + let chosenAlgoServiceId = servicesAlgo[0].id; + if (typeof algoServiceIdInput === 'string' && algoServiceIdInput.trim().length > 0) { + const expectedAlgoServiceId = algoServiceIdInput.trim(); + const matchAlgoSvc = servicesAlgo.find((s: any) => s.id === expectedAlgoServiceId); + if (!matchAlgoSvc) { + console.error( + `Algorithm Service ID "${expectedAlgoServiceId}" not found in algo DDO ${algoDdo.id}. ` + + 'Provide a valid service.id from the algorithm asset or omit the argument to use the default (services[0]).' + ); + return; + } + chosenAlgoServiceId = expectedAlgoServiceId; + } + const algo: ComputeAlgorithm = { + documentId: algoDdo.id, + serviceId: chosenAlgoServiceId, + meta: metadataAlgo.algorithm, + }; + + const assetAlgo: { + documentId: string; + serviceId: string; + asset: Asset; + version?: string; + } = { + documentId: algoDdo.id, + serviceId: chosenAlgoServiceId, + asset: algoDdo, + version: versionAlgo + }; + const assets = []; + for (const dataDdo in ddos) { + const ddoInstanceDdo = DDOManager.getDDOClass(ddos[dataDdo]); + const { services: servicesDdo, version: versionDdo } = ddoInstanceDdo.getDDOFields(); + let chosenServiceId = servicesDdo[0].id; + if (inputServices.length > 0) { + const expectedServiceId = inputServices[Number(dataDdo)]; + const match = servicesDdo.find((s: any) => s.id === expectedServiceId); + if (!match) { + console.error( + `Service ID "${expectedServiceId}" not found in dataset ${inputDatasets[Number(dataDdo)]}. ` + + 'Ensure serviceIds[i] exists in the corresponding dataset services.' + ); + return; + } + chosenServiceId = expectedServiceId; + if (Number(dataDdo) === 0 && match.serviceEndpoint) { + providerURI = match.serviceEndpoint; + } + } else { + if (Number(dataDdo) === 0 && servicesDdo[0]?.serviceEndpoint) { + providerURI = servicesDdo[0].serviceEndpoint; + } + } + const canStartCompute = isOrderable( + ddos[dataDdo], + chosenServiceId, + algo, + algoDdo + ); + if (!canStartCompute) { + console.error( + "Error Cannot start compute job using the datasets DIDs & algorithm DID provided" + ); + return; + } + assets.push({ + documentId: ddos[dataDdo].id, + serviceId: chosenServiceId, + asset: ddos[dataDdo], + version: versionDdo + }); + } + const maxJobDuration = Number(args[4]) + if (!maxJobDuration) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because maxJobDuration was not provided." + ); + return; + } + if (maxJobDuration < 0) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because maxJobDuration is less than 0. It should be in seconds." + ); + return; + } + let supportedMaxJobDuration: number = maxJobDuration; + if (maxJobDuration > computeEnv.maxJobDuration) { + supportedMaxJobDuration = computeEnv.maxJobDuration; + } + const paymentToken = args[5] + if (!paymentToken) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because paymentToken was not provided." + ); + return; + } + const { chainId } = await this.signer.provider.getNetwork() + if (!Object.keys(computeEnv.fees).includes(chainId.toString())) { + console.error( + "Error starting paid compute using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because chainId is not supported by compute environment. " + + args[3] + + ". Supported chain IDs: " + + computeEnv.fees.keys() + ); + return; + } + let found: boolean = false; + for (const fee of computeEnv.fees[chainId.toString()]) { + if (fee.feeToken.toLowerCase() === paymentToken.toLowerCase()) { + found = true; + break; + } + } + if (found === false) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because paymentToken is not supported by this environment " + + args[3] + ); + return; + } + const resources = args[6] // resources object should be stringified in cli when calling initializeCompute + if (!resources) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because resources for compute were not provided." + ); + return; + } + const policiesServer = await getPolicyServerOBJs(assets, assetAlgo, this.signer, this.oceanNodeUrl); + const parsedResources = JSON.parse(resources); + const providerInitializeComputeJob = + await ProviderInstance.initializeCompute( + assets, + algo, + computeEnv.id, + paymentToken, + supportedMaxJobDuration, + providerURI, + this.signer, // V1 was this.signer.getAddress() + parsedResources, + Number(chainId), + policiesServer + ); + if ( + !providerInitializeComputeJob || + "error" in providerInitializeComputeJob.algorithm + ) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + ); + return; + } + console.log(chalk.yellow('\n--- Payment Details ---')); + console.log(JSON.stringify(providerInitializeComputeJob, null, 2)); + return providerInitializeComputeJob; + + } + + public async computeStart(args: string[]) { + const inputDatasetsString = args[1]; + let inputDatasets = []; + + if (!inputDatasetsString || inputDatasetsString.trim() === '[]') { + inputDatasets = []; + } else { + const cleaned = inputDatasetsString.replaceAll('[', '').replaceAll(']', ''); + inputDatasets = cleaned.split(',').map(s => s.trim()).filter(Boolean); + } + + const inputServicesString = args[8]; + let inputServices: string[] = []; + if (typeof inputServicesString === 'string' && inputServicesString.trim().length > 0) { + inputServices = inputServicesString.split(',').map(s => s.trim()).filter(Boolean); + } else if (Array.isArray(inputServicesString)) { + inputServices = inputServicesString.map(String).map(s => s.trim()).filter(Boolean); + } + + + const ddos = []; + + for (const dataset in inputDatasets) { + const dataDdo = await this.aquarius.waitForIndexer( + inputDatasets[dataset], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!dataDdo) { + console.error( + "Error fetching DDO " + dataset[1] + ". Does this asset exists?" + ); + return; + } else { + ddos.push(dataDdo); + } + } + if ( + inputDatasets.length > 0 && + (ddos.length <= 0 || ddos.length != inputDatasets.length) + ) { + console.error("Not all the data ddos are available."); + return; + } + let providerURI = this.oceanNodeUrl; + const ddoInstance = DDOManager.getDDOClass(ddos[0]); + const { services } = ddoInstance.getDDOFields(); + if (ddos.length > 0) { + providerURI = services[0].serviceEndpoint; + } + const algoDdo = await this.aquarius.waitForIndexer( + args[2], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!algoDdo) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + + const computeEnvs = await ProviderInstance.getComputeEnvironments( + this.oceanNodeUrl + ); + + if (!computeEnvs || computeEnvs.length < 1) { + console.error( + "Error fetching compute environments. No compute environments available." + ); + return; + } + const computeEnvID = args[3]; + // NO chainId needed anymore (is not part of ComputeEnvironment spec anymore) + // const chainComputeEnvs = computeEnvs[computeEnvID]; // was algoDdo.chainId + let computeEnv = null; // chainComputeEnvs[0]; + + if (computeEnvID && computeEnvID.length > 1) { + for (const index in computeEnvs) { + if (computeEnvID == computeEnvs[index].id) { + computeEnv = computeEnvs[index]; + break; + } + } + } + if (!computeEnv || !computeEnvID) { + console.error( + "Error fetching compute environment. No compute environment matches id: ", + computeEnvID + ); + return; + } + const ddoInstanceAlgo = DDOManager.getDDOClass(algoDdo); + const { services: servicesAlgo, metadata: metadataAlgo, version: versionAlgo } = ddoInstanceAlgo.getDDOFields(); + const algoServiceIdInput = args[9] as string | undefined; + let chosenAlgoServiceId = servicesAlgo[0].id; + if (typeof algoServiceIdInput === 'string' && algoServiceIdInput.trim().length > 0) { + const expectedAlgoServiceId = algoServiceIdInput.trim(); + const matchAlgoSvc = servicesAlgo.find((s: any) => s.id === expectedAlgoServiceId); + if (!matchAlgoSvc) { + console.error( + `Algorithm Service ID "${expectedAlgoServiceId}" not found in algo DDO ${algoDdo.id}. ` + + 'Provide a valid service.id from the algorithm asset or omit the argument to use the default (services[0]).' + ); + return; + } + chosenAlgoServiceId = expectedAlgoServiceId; + } + const algoServiceIndex = servicesAlgo.findIndex((s: any) => s.id === chosenAlgoServiceId); + if (algoServiceIndex < 0) { + console.error(`Could not resolve serviceIndex for algorithm serviceId ${chosenAlgoServiceId}`); + return; + } + const algo: ComputeAlgorithm = { + documentId: algoDdo.id, + serviceId: chosenAlgoServiceId, + meta: metadataAlgo.algorithm, + }; + + const assetAlgo: { + documentId: string; + serviceId: string; + asset: Asset; + version?: string; + } = { + documentId: algoDdo.id, + serviceId: chosenAlgoServiceId, + asset: algoDdo, + version: versionAlgo + }; + + const assets = []; + const datasetServiceIndex: number[] = []; + for (const dataDdo in ddos) { + const ddoInstanceDdo = DDOManager.getDDOClass(ddos[dataDdo]); + const { services: servicesDdo, version: versionDdo } = ddoInstanceDdo.getDDOFields(); + let chosenServiceId = servicesDdo[0].id; + if (inputServices.length > 0) { + const expectedServiceId = inputServices[Number(dataDdo)]; + const match = servicesDdo.find((s: any) => s.id === expectedServiceId); + if (!match) { + console.error( + `Service ID "${expectedServiceId}" not found in dataset ${inputDatasets[Number(dataDdo)]}. ` + + 'Ensure serviceIds[i] exists in the corresponding dataset services.' + ); + return; + } + chosenServiceId = expectedServiceId; + if (Number(dataDdo) === 0 && match.serviceEndpoint) { + providerURI = match.serviceEndpoint; + } + } else { + if (Number(dataDdo) === 0 && servicesDdo[0]?.serviceEndpoint) { + providerURI = servicesDdo[0].serviceEndpoint; + } + } + const chosenServiceIndex = servicesDdo.findIndex((s: any) => s.id === chosenServiceId); + if (chosenServiceIndex < 0) { + console.error( + `Could not resolve serviceIndex for dataset ${ddos[dataDdo].id} with serviceId ${chosenServiceId}` + ); + return; + } + datasetServiceIndex.push(chosenServiceIndex); + const canStartCompute = isOrderable( + ddos[dataDdo], + chosenServiceId, + algo, + algoDdo + ); + if (!canStartCompute) { + console.error( + "Error Cannot start compute job using the datasets DIDs & algorithm DID provided" + ); + return; + } + assets.push({ + documentId: ddos[dataDdo].id, + serviceId: chosenServiceId, + asset: ddos[dataDdo], + version: versionDdo + }); + } + const providerInitializeComputeJob = args[4]; // provider fees + payment + const parsedProviderInitializeComputeJob = fixAndParseProviderFees(providerInitializeComputeJob) + console.log("Ordering algorithm: ", args[2]); + const datatoken = new Datatoken( + this.signer, + (await this.signer.provider.getNetwork()).chainId.toString(), + this.config + ); + algo.transferTxId = await handleComputeOrder( + parsedProviderInitializeComputeJob?.algorithm, + algoDdo, + this.signer, + computeEnv.consumerAddress, + algoServiceIndex, + datatoken, + this.config, + parsedProviderInitializeComputeJob?.algorithm?.providerFee, + providerURI + ); + if (!algo.transferTxId) { + console.error( + "Error ordering compute for algorithm with DID: " + + args[2] + + ". Do you have enough tokens?" + ); + return; + } + console.log("Ordering assets: ", args[1]); + + for (let i = 0; i < ddos.length; i++) { + assets[i].transferTxId = await handleComputeOrder( + parsedProviderInitializeComputeJob?.datasets[i], + ddos[i], + this.signer, + computeEnv.consumerAddress, + datasetServiceIndex[i], + datatoken, + this.config, + parsedProviderInitializeComputeJob?.datasets[i].providerFee, + providerURI + ); + if (!assets[i].transferTxId) { + console.error( + "Error ordering dataset with DID: " + + assets[i] + + ". Do you have enough tokens?" + ); + return; + } + } + // payment check + const maxJobDuration = Number(args[5]) + if (!maxJobDuration) { + console.error( + "Error initializing Provider for the compute job using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because maxJobDuration was not provided." + ); + return; + } + if (maxJobDuration < 0) { + console.error( + "Error starting paid compute using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because maxJobDuration is less than 0. It should be in seconds." + ); + return; + } + let supportedMaxJobDuration: number = maxJobDuration; + if (maxJobDuration > computeEnv.maxJobDuration) { + supportedMaxJobDuration = computeEnv.maxJobDuration; + } + const { chainId } = await this.signer.provider.getNetwork() + const paymentToken = args[6] + if (!paymentToken) { + console.error( + "Error starting paid compute using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because paymentToken was not provided." + ); + return; + } + if (!Object.keys(computeEnv.fees).includes(chainId.toString())) { + console.error( + "Error starting paid compute using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because chainId is not supported by compute environment. " + + args[3] + + ". Supported chain IDs: " + + computeEnv.fees.keys() + ); + return; + } + let found: boolean = false; + for (const fee of computeEnv.fees[chainId.toString()]) { + if (fee.feeToken.toLowerCase() === paymentToken.toLowerCase()) { + found = true; + break; + } + } + if (found === false) { + console.error( + "Error starting paid compute using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because paymentToken is not supported by this environment " + + args[3] + ); + return; + } + const resources = args[7] // resources object should be stringified in cli when calling initializeCompute + if (!resources) { + console.error( + "Error starting paid compute using dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because resources for compute were not provided." + ); + return; + } + + const escrow = new EscrowContract( + getAddress(parsedProviderInitializeComputeJob.payment.escrowAddress), + this.signer + ); + console.log("Verifying payment..."); + await new Promise((resolve) => setTimeout(resolve, 3000)); + + const validationEscrow = await escrow.verifyFundsForEscrowPayment( + paymentToken, + computeEnv.consumerAddress, + await unitsToAmount( + this.signer, + paymentToken, + parsedProviderInitializeComputeJob.payment.amount + ), + parsedProviderInitializeComputeJob.payment.amount.toString(), + parsedProviderInitializeComputeJob.payment.minLockSeconds.toString(), + "10" + ); + if (validationEscrow.isValid === false) { + console.error( + "Error starting compute job dataset DID " + + args[1] + + " and algorithm DID " + + args[2] + + " because escrow funds check failed: " + + validationEscrow.message + ); + return; + } + + console.log("Starting compute job using provider: ", providerURI); + + const output: ComputeOutput = { + metadataUri: await getMetadataURI(), + }; + const policiesServer = await getPolicyServerOBJs(assets, assetAlgo, this.signer, this.oceanNodeUrl); + + const computeJobs = await ProviderInstance.computeStart( + providerURI, + this.signer, + computeEnv.id, + assets, // assets[0] // only c2d v1, + algo, + supportedMaxJobDuration, + paymentToken, + JSON.parse(resources), + Number((await this.signer.provider.getNetwork()).chainId), + null, + null, + // additionalDatasets, only c2d v1 + output, + policiesServer + ); + + console.log("computeJobs: ", computeJobs); + + if (computeJobs && computeJobs[0]) { + const { jobId, payment } = computeJobs[0]; + console.log("Compute started. JobID: " + jobId); + console.log("Agreement ID: " + payment.lockTx); + } else { + console.log("Error while starting the compute job: ", computeJobs); + } + } + + public async freeComputeStart(args: string[]) { + const inputDatasetsString = args[1]; + let inputDatasets = []; + + if (!inputDatasetsString || inputDatasetsString.trim() === '[]') { + inputDatasets = []; + } else { + const cleaned = inputDatasetsString.replaceAll('[', '').replaceAll(']', ''); + inputDatasets = cleaned.split(',').map(s => s.trim()).filter(Boolean); + } + const inputServicesString = args[4]; + let inputServices: string[] = []; + if (typeof inputServicesString === 'string' && inputServicesString.trim().length > 0) { + inputServices = inputServicesString.split(',').map(s => s.trim()).filter(Boolean); + } else if (Array.isArray(inputServicesString)) { + inputServices = inputServicesString.map(String).map(s => s.trim()).filter(Boolean); + } + const ddos = []; + + for (const dataset in inputDatasets) { + const dataDdo = await this.aquarius.waitForIndexer( + inputDatasets[dataset], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!dataDdo) { + console.error( + "Error fetching DDO " + dataset[1] + ". Does this asset exists?" + ); + return; + } else { + ddos.push(dataDdo); + } + } + + if ( + inputDatasets.length > 0 && + (ddos.length <= 0 || ddos.length != inputDatasets.length) + ) { + console.error("Not all the data ddos are available."); + return; + } + let providerURI = this.oceanNodeUrl; + const ddoInstance = DDOManager.getDDOClass(ddos[0]); + const { services } = ddoInstance.getDDOFields(); + if (ddos.length > 0) { + providerURI = services[0].serviceEndpoint; + } + + const algoDdo = await this.aquarius.waitForIndexer( + args[2], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!algoDdo) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + + const computeEnvs = await ProviderInstance.getComputeEnvironments( + this.oceanNodeUrl + ); + if (!computeEnvs || computeEnvs.length < 1) { + console.error( + "Error fetching compute environments. No compute environments available." + ); + return; + } + + const mytime = new Date(); + const computeMinutes = 5; + mytime.setMinutes(mytime.getMinutes() + computeMinutes); + + const computeEnvID = args[3]; + // NO chainId needed anymore (is not part of ComputeEnvironment spec anymore) + // const chainComputeEnvs = computeEnvs[computeEnvID]; // was algoDdo.chainId + let computeEnv = null; // chainComputeEnvs[0]; + if (computeEnvID && computeEnvID.length > 1) { + for (const env of computeEnvs) { + if (computeEnvID == env.id && env.free) { + computeEnv = env; + break; + } + } + } + + if (!computeEnv || !computeEnvID) { + console.error( + "Error fetching free compute environment. No free compute environment matches id: ", + computeEnvID + ); + return; + } + const ddoInstanceAlgo = DDOManager.getDDOClass(algoDdo); + const { services: servicesAlgo, metadata: metadataAlgo, version: versionAlgo } = ddoInstanceAlgo.getDDOFields(); + + const algoServiceIdInput = args[5] as string | undefined; + let chosenAlgoServiceId = servicesAlgo[0].id; + if (typeof algoServiceIdInput === 'string' && algoServiceIdInput.trim().length > 0) { + const expectedAlgoServiceId = algoServiceIdInput.trim(); + const matchAlgoSvc = servicesAlgo.find((s: any) => s.id === expectedAlgoServiceId); + if (!matchAlgoSvc) { + console.error( + `Algorithm Service ID "${expectedAlgoServiceId}" not found in algo DDO ${algoDdo.id}. ` + + 'Provide a valid service.id from the algorithm asset or omit the argument to use the default (services[0]).' + ); + return; + } + chosenAlgoServiceId = expectedAlgoServiceId; + } + const algo: ComputeAlgorithm = { + documentId: algoDdo.id, + serviceId: chosenAlgoServiceId, + meta: metadataAlgo.algorithm, + }; + + const assetAlgo: { + documentId: string; + serviceId: string; + asset: Asset; + version?: string; + } = { + documentId: algoDdo.id, + serviceId: chosenAlgoServiceId, + asset: algoDdo, + version: versionAlgo + }; + + const assets = []; + for (const dataDdo in ddos) { + const ddoInstanceDdo = DDOManager.getDDOClass(ddos[dataDdo]); + const { services: servicesDdo, version: versionDdo } = ddoInstanceDdo.getDDOFields(); + let chosenServiceId = servicesDdo[0].id; + if (inputServices.length > 0) { + const expectedServiceId = inputServices[Number(dataDdo)]; + const match = servicesDdo.find((s: any) => s.id === expectedServiceId); + if (!match) { + console.error( + `Service ID "${expectedServiceId}" not found in dataset ${inputDatasets[Number(dataDdo)]}. ` + + 'Ensure serviceIds[i] exists in the corresponding dataset services.' + ); + return; + } + chosenServiceId = expectedServiceId; + if (Number(dataDdo) === 0 && match.serviceEndpoint) { + providerURI = match.serviceEndpoint; + } + } else { + if (Number(dataDdo) === 0 && servicesDdo[0]?.serviceEndpoint) { + providerURI = servicesDdo[0].serviceEndpoint; + } + } + const canStartCompute = isOrderable( + ddos[dataDdo], + chosenServiceId, + algo, + algoDdo + ); + if (!canStartCompute) { + console.error( + "Error Cannot start compute job using the datasets DIDs & algorithm DID provided" + ); + return; + } + assets.push({ + documentId: ddos[dataDdo].id, + serviceId: chosenServiceId, + asset: ddos[dataDdo], + version: versionDdo + }); + } + + const output: ComputeOutput = { + metadataUri: await getMetadataURI(), + }; + + const policiesServer = await getPolicyServerOBJs(assets, assetAlgo, this.signer, this.oceanNodeUrl); + const computeJobs = await ProviderInstance.freeComputeStart( + providerURI, + this.signer, + computeEnv.id, + assets, // assets[0] // only c2d v1, + algo, + null, + null, + null, + output, + policiesServer + ); + + + if (computeJobs && computeJobs[0]) { + const { jobId } = computeJobs[0]; + console.log("Compute started. JobID: " + jobId); + } else { + console.log("Error while starting the compute job: ", computeJobs); + } + } + + public async computeStop(args: string[]) { + const dataDdo = await this.aquarius.waitForIndexer( + args[1], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!dataDdo) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + + const jobId = args[2]; + const jobStatus = await ProviderInstance.computeStop( + jobId, + this.oceanNodeUrl, + this.signer + ); + console.log(jobStatus); + } + + public async getComputeEnvironments() { + const computeEnvs = await ProviderInstance.getComputeEnvironments( + this.oceanNodeUrl + ); + + if (!computeEnvs || computeEnvs.length < 1) { + console.error( + "Error fetching compute environments. No compute environments available." + ); + return; + } + + console.log("Exiting compute environments: ", JSON.stringify(computeEnvs)); + } + + public async computeStreamableLogs(args: string[]) { + const jobId = args[0]; + const logsResponse = await ProviderInstance.computeStreamableLogs( + this.oceanNodeUrl, + this.signer, + jobId + ); + console.log("response: ", logsResponse); + + if (!logsResponse) { + console.error("Error fetching streamable logs. No logs available."); + return; + } else { + const stream = logsResponse as ReadableStream; + console.log("stream: ", stream); + const text = await new Response(stream).text(); + console.log("Streamable Logs: "); + console.log(text); + // for await (const value of stream) { + // // just print it to the console + // console.log(value); + // } + } + console.log("Exiting computeStreamableLogs: ", logsResponse); + } + + public async allowAlgo(args: string[]) { + const asset = await this.aquarius.waitForIndexer( + args[1], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + + if (!asset) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + const ddoInstance = DDOManager.getDDOClass(asset); + const { indexedMetadata } = ddoInstance.getAssetFields(); + const { services } = ddoInstance.getDDOFields(); + if (indexedMetadata.nft.owner !== (await this.signer.getAddress())) { + console.error( + "You are not the owner of this asset, and there for you cannot update it." + ); + return; + } + + if (services[0].type !== "compute") { + console.error( + "Error getting computeService for " + + args[1] + + ". Does this asset has an computeService?" + ); + return; + } + const algoAsset = await this.aquarius.waitForIndexer( + args[2], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!algoAsset) { + console.error( + "Error fetching DDO " + args[2] + ". Does this asset exists?" + ); + return; + } + const algoInstance = DDOManager.getDDOClass(algoAsset); + const { services: servicesAlgo, metadata: metadataAlgo } = algoInstance.getDDOFields(); + const encryptDDO = args[3] === "false" ? false : true; + let filesChecksum; + try { + filesChecksum = await ProviderInstance.checkDidFiles( + algoAsset.id, + servicesAlgo[0].id, + servicesAlgo[0].serviceEndpoint, + true + ); + } catch (e) { + console.error("Error checking algo files: ", e); + return; + } + + const containerChecksum = + metadataAlgo.algorithm.container.entrypoint + + metadataAlgo.algorithm.container.checksum; + const trustedAlgorithm = { + did: algoAsset.id, + containerSectionChecksum: getHash(containerChecksum), + filesChecksum: filesChecksum?.[0]?.checksum, + serviceId: servicesAlgo[0].id, + }; + services[0].compute.publisherTrustedAlgorithms.push(trustedAlgorithm); + try { + const txid = await updateAssetMetadata( + this.signer, + asset, + this.oceanNodeUrl, + this.aquarius, + encryptDDO + ); + console.log("Successfully updated asset metadata: " + txid); + } catch (e) { + console.error("Error updating asset metadata: ", e); + return; + } + } + + public async disallowAlgo(args: string[]) { + const asset = await this.aquarius.waitForIndexer( + args[1], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!asset) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + const ddoInstance = DDOManager.getDDOClass(asset); + const { indexedMetadata } = ddoInstance.getAssetFields(); + const { services } = ddoInstance.getDDOFields(); + if (indexedMetadata.nft.owner !== (await this.signer.getAddress())) { + console.error( + "You are not the owner of this asset, and there for you cannot update it." + ); + return; + } + if (services[0].type !== "compute") { + console.error( + "Error getting computeService for " + + args[1] + + ". Does this asset has an computeService?" + ); + return; + } + if (services[0].compute.publisherTrustedAlgorithms) { + console.error( + " " + args[1] + ". Does this asset has an computeService?" + ); + return; + } + const encryptDDO = args[3] === "false" ? false : true; + const indexToDelete = + services[0].compute.publisherTrustedAlgorithms.findIndex( + (item) => item.did === args[2] + ); + + if (indexToDelete !== -1) { + services[0].compute.publisherTrustedAlgorithms.splice( + indexToDelete, + 1 + ); + } else { + console.error( + " " + + args[2] + + ". is not allowed by the publisher to run on " + + args[1] + ); + return; + } + + const txid = await updateAssetMetadata( + this.signer, + asset, + this.oceanNodeUrl, + this.aquarius, + encryptDDO + ); + console.log("Asset updated " + txid); + } + + public async getJobStatus(args: string[]) { + // args[1] - did (for checking if data asset exists, legacy) + // args[2] - jobId + // args[3] - agreementId + const hasAgreementId = args.length === 4; + + const dataDdo = await this.aquarius.waitForIndexer( + args[1], + null, + null, + this.indexingParams.retryInterval, + this.indexingParams.maxRetries + ); + if (!dataDdo) { + console.error( + "Error fetching DDO " + args[1] + ". Does this asset exists?" + ); + return; + } + const jobId = args[2]; + let agreementId = null; + if (hasAgreementId) { + agreementId = args[3]; + } + + const jobStatus = (await ProviderInstance.computeStatus( + this.oceanNodeUrl, + await this.signer.getAddress(), + jobId, + agreementId + )) as ComputeJob; + console.log(util.inspect(jobStatus, false, null, true)); + } + + public async downloadJobResults(args: string[]) { + const jobResult = await ProviderInstance.getComputeResultUrl( + this.oceanNodeUrl, + this.signer, + args[1], + parseInt(args[2]) + ); + console.log("jobResult ", jobResult); + + try { + const path = args[3] ? args[3] : "."; + const { filename } = await downloadFile( + jobResult, + path, + parseInt(args[2]) + ); + console.log("File downloaded successfully:", path + "/" + filename); + } catch (e) { + console.log(`Download url dataset failed: ${e}`); + } + } + + public async mintOceanTokens() { + try { + const config = await getConfigByChainId(Number(this.config.chainId)); + const minAbi = [ + { + constant: false, + inputs: [ + { name: "to", type: "address" }, + { name: "value", type: "uint256" }, + ], + name: "mint", + outputs: [{ name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + ]; + + const tokenContract = new ethers.Contract( + config?.Ocean, + minAbi, + this.signer + ); + const estGasPublisher = await tokenContract.mint.estimateGas( + await this.signer.getAddress(), + await amountToUnits(null, null, "1000", 18) + ); + const tx = await sendTx( + estGasPublisher, + this.signer, + 1, + tokenContract.mint, + await this.signer.getAddress(), + amountToUnits(null, null, "1000", 18) + ); + await tx.wait(); + } catch (error) { + console.error("Error minting Ocean tokens:", error); + } + } + + public async generateAuthToken() { + const authToken = await ProviderInstance.generateAuthToken( + this.signer, + this.oceanNodeUrl + ); + console.log(`Auth token successfully generated: ${authToken}`); + } + + public async invalidateAuthToken(args: string[]) { + const authToken = args[0]; + const result = await ProviderInstance.invalidateAuthToken( + this.signer, + authToken, + this.oceanNodeUrl + ); + if (!result.success) { + console.log("Auth token could not be invalidated"); + return; + } + + console.log(`Auth token successfully invalidated`); + } + + public async getEscrowBalance(token: string): Promise { + const config = await getConfigByChainId(Number(this.config.chainId)); + const escrow = new EscrowContract( + getAddress(config.Escrow), + this.signer, + Number(this.config.chainId) + ); + + try { + const balance = await escrow.getUserFunds( + await this.signer.getAddress(), + token + ); + const decimals = await getTokenDecimals(this.signer, token); + const available = balance.available; + const amount = await unitsToAmount( + this.signer, + token, + available, + decimals + ); + console.log(`Escrow user funds for token ${token}: ${amount}`); + return Number(amount); + } catch (error) { + console.error("Error getting escrow balance:", error); + } + } + + public async withdrawFromEscrow( + token: string, + amount: string + ): Promise { + const config = await getConfigByChainId(Number(this.config.chainId)); + const escrow = new EscrowContract( + getAddress(config.Escrow), + this.signer, + Number(this.config.chainId) + ); + + const balance = await this.getEscrowBalance(token); + if (balance < Number(amount)) { + console.error(`Insufficient balance in escrow for token ${token}`); + return; + } + + const withdrawTx = await escrow.withdraw([token], [amount]); + await withdrawTx.wait(); + console.log(`Successfully withdrawn ${amount} ${token} from escrow`); + } + + public async depositToEscrow( + signer: Signer, + token: string, + amount: string, + chainId: number + ) { + try { + const amountInUnits = await amountToUnits(signer, token, amount, 18); + const config = await getConfigByChainId(chainId); + const escrowAddress = config.Escrow; + + const tokenContract = new ethers.Contract( + token, + ["function approve(address spender, uint256 amount) returns (bool)"], + signer + ); + + const escrow = new EscrowContract( + getAddress(escrowAddress), + signer, + chainId + ); + + console.log("Approving token transfer..."); + const approveTx = await tokenContract.approve( + escrowAddress, + amountInUnits + ); + await approveTx.wait(); + console.log(`Successfully approved ${amount} ${token} to escrow`); + + console.log("Depositing to escrow..."); + const depositTx = await escrow.deposit(token, amount); + await depositTx.wait(); + return true; + } catch (error) { + console.error("Error depositing to escrow:", error); + return false; + } + } + + public async authorizeEscrowPayee( + token: string, + payee: string, + maxLockedAmount: string, + maxLockSeconds: string, + maxLockCounts: string + ) { + try { + const config = await getConfigByChainId(Number(this.config.chainId)); + const escrowAddress = config.Escrow; + + const escrow = new EscrowContract(getAddress(escrowAddress), this.signer); + + console.log("Authorizing payee..."); + const authorizeTx = await escrow.authorize( + getAddress(token), + getAddress(payee), + maxLockedAmount, + maxLockSeconds, + maxLockCounts + ); + await authorizeTx.wait(); + console.log(`Successfully authorized payee ${payee} for token ${token}`); + + return true; + } catch (error) { + console.error("Error authorizing payee:", error); + return false; + } + } + + public async getAuthorizationsEscrow(token: string, payee: string) { + const config = await getConfigByChainId(Number(this.config.chainId)); + const payer = await this.signer.getAddress(); + const tokenAddress = getAddress(token); + const payerAddress = getAddress(payer); + const payeeAddress = getAddress(payee); + const decimals = await getTokenDecimals(this.signer, token); + const escrow = new EscrowContract( + getAddress(config.Escrow), + this.signer, + Number(this.config.chainId) + ); + + const authorizations = await escrow.getAuthorizations( + tokenAddress, + payerAddress, + payeeAddress + ); + const authorization = authorizations[0]; + if (!authorization || authorization.length === 0) { + console.log("No authorizations found"); + return; + } + + const currentLockedAmount = await unitsToAmount( + this.signer, + token, + authorization.currentLockedAmount.toString(), + decimals + ); + const maxLockedAmount = await unitsToAmount( + this.signer, + token, + authorization.maxLockedAmount.toString(), + decimals + ); + + console.log("Authorizations found:"); + console.log(`- Current Locked Amount: ${Number(currentLockedAmount)}`); + console.log(`- Current Locks: ${authorization.currentLocks}`); + console.log(`- Max locked amount: ${Number(maxLockedAmount)}`); + console.log(`- Max lock seconds: ${authorization.maxLockSeconds}`); + console.log(`- Max lock counts: ${authorization.maxLockCounts}`); + + return authorizations; + } + + public async createAccessList(args: string[]): Promise { + try { + const name = args[0]; + const symbol = args[1]; + const transferable = args[2] === "true"; + const initialUsers = args[3] + ? args[3].split(",").map((u) => u.trim()) + : []; + + if (!name || !symbol) { + console.error(chalk.red("Name and symbol are required")); + return; + } + + const config = await getConfigByChainId(Number(this.config.chainId)); + if (!config.AccessListFactory) { + console.error( + chalk.red( + "Access list factory not found. Check local address.json file" + ) + ); + return; + } + const accessListFactory = new AccesslistFactory( + config.AccessListFactory, + this.signer, + Number(this.config.chainId) + ); + + const owner = await this.signer.getAddress(); + const tokenURIs = initialUsers.map( + () => "https://oceanprotocol.com/nft/" + ); + + console.log(chalk.cyan("Creating new access list...")); + console.log(`Name: ${name}`); + console.log(`Symbol: ${symbol}`); + console.log(`Transferable: ${transferable}`); + console.log(`Owner: ${owner}`); + console.log( + `Initial users: ${initialUsers.length > 0 ? initialUsers.join(", ") : "none" + }` + ); + + const accessListAddress = + await accessListFactory.deployAccessListContract( + name, + symbol, + tokenURIs, + transferable, + owner, + initialUsers + ); + + console.log(chalk.green(`\nAccess list created successfully!`)); + console.log(chalk.green(`Contract address: ${accessListAddress}`)); + } catch (error) { + console.error(chalk.red("Error creating access list:"), error); + } + } + + public async addToAccessList(args: string[]): Promise { + try { + const accessListAddress = args[0]; + const users = args[1].split(",").map((u) => u.trim()); + + if (!accessListAddress || users.length === 0) { + console.error( + chalk.red("Access list address and at least one user are required") + ); + return; + } + + const accessList = new AccessListContract( + accessListAddress, + this.signer, + Number(this.config.chainId) + ); + + console.log( + chalk.cyan(`Adding ${users.length} user(s) to access list...`) + ); + + if (users.length === 1) { + const tx = await accessList.mint( + users[0], + "https://oceanprotocol.com/nft/" + ); + await tx.wait(); + console.log( + chalk.green(`Successfully added user ${users[0]} to access list`) + ); + return; + } + + const tokenURIs = users.map(() => "https://oceanprotocol.com/nft/"); + const tx = await accessList.batchMint(users, tokenURIs); + await tx.wait(); + console.log( + chalk.green(`Successfully added ${users.length} users to access list:`) + ); + users.forEach((user) => console.log(` - ${user}`)); + } catch (error) { + console.error(chalk.red("Error adding users to access list:"), error); + } + } + + public async checkAccessList(args: string[]): Promise { + try { + const accessListAddress = args[0]; + const users = args[1].split(",").map((u) => u.trim()); + + if (!accessListAddress || users.length === 0) { + console.error( + chalk.red("Access list address and at least one user are required") + ); + return; + } + + const accessList = new AccessListContract( + accessListAddress, + this.signer, + Number(this.config.chainId) + ); + + console.log( + chalk.cyan(`Checking access list for ${users.length} user(s)...\n`) + ); + + for (const user of users) { + const balance = await accessList.balance(user); + const hasAccess = Number(balance) > 0; + + if (hasAccess) { + console.log( + chalk.green(`✓ ${user}: Has access (balance: ${balance})`) + ); + } else { + console.log(chalk.red(`✗ ${user}: No access`)); + } + } + } catch (error) { + console.error(chalk.red("Error checking access list:"), error); + } + } + + public async removeFromAccessList(args: string[]): Promise { + try { + const accessListAddress = args[0]; + const users = args[1].split(",").map((u) => u.trim()); + + if (!accessListAddress || users.length === 0) { + console.error( + chalk.red( + "Access list address and at least one user address are required" + ) + ); + return; + } + + const accessList = new AccessListContract( + accessListAddress, + this.signer, + Number(this.config.chainId) + ); + + console.log( + chalk.cyan(`Removing ${users.length} user(s) from access list...`) + ); + for (const user of users) { + const balance = await accessList.balance(user); + + if (Number(balance) === 0) { + console.log( + chalk.yellow( + `⚠ User ${user} is not on the access list, skipping...` + ) + ); + continue; + } + + const balanceNum = Number(balance); + const contract = accessList.contract; + + let removedCount = 0; + for (let index = 0; index < balanceNum; index++) { + try { + const tokenId = await contract.tokenOfOwnerByIndex(user, index); + const tx = await accessList.burn(Number(tokenId)); + await tx.wait(); + + console.log( + chalk.green( + `✓ Successfully removed user ${user} (token ID: ${tokenId})` + ) + ); + removedCount++; + } catch (e: any) { + console.log( + chalk.yellow( + `⚠ Could not remove token at index ${index} for user ${user}: ${e.message}` + ) + ); + } + } + + if (removedCount === 0) { + console.log( + chalk.yellow(`⚠ Could not remove any tokens for user ${user}`) + ); + } else if (removedCount < balanceNum) { + console.log( + chalk.yellow( + `⚠ Only removed ${removedCount} of ${balanceNum} tokens for user ${user}` + ) + ); + } + } + } catch (error) { + console.error(chalk.red("Error removing users from access list:"), error); + } + } + + public async downloadNodeLogs(args: string[]): Promise { + try { + const outputLocation = args[0]; + const last = args[1]; + let from = args[2]; + let to = args[3]; + const maxLogs = args[4] ? Math.min(parseInt(args[4], 10), 1000) : undefined; + + if (!outputLocation) { + console.error(chalk.red("Output location is required")); + return; + } + + if (!fs.existsSync(outputLocation)) { + console.error( + chalk.red(`Output directory does not exist: ${outputLocation}`) + ); + return; + } + + if (last && (from || to)) { + console.error( + chalk.red("Use either --last or --from/--to, not both") + ); + return; + } + + if ((from && !to) || (!from && to)) { + console.error( + chalk.red( + "Both --from and --to are required when specifying a time range" + ) + ); + return; + } + + if (!last && !from && !to) { + to = `${Date.now()}`; + from = `${Date.now() - 60 * 60 * 1000}`; // default: last 1 hour + } + + if (last) { + to = `${Date.now()}`; + from = `${Date.now() - parseInt(last, 10) * 60 * 60 * 1000}`; + } + + const response = await ProviderInstance.downloadNodeLogs( + this.oceanNodeUrl, + this.signer, + from, + to, + maxLogs + ); + + const text = await new Response(response).text(); + const outputPath = `${outputLocation}/logs.json`; + fs.writeFileSync(outputPath, text); + console.log(chalk.green(`Logs saved to ${outputPath}`)); + } catch (error) { + console.error(chalk.red("Error downloading node logs: "), error); + } + } } diff --git a/src/helpers.ts b/src/helpers.ts index 17280f7..8b692e7 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -3,7 +3,7 @@ import fetch from "cross-fetch"; import { promises as fs, readFileSync } from "fs"; import * as path from "path"; import * as sapphire from '@oasisprotocol/sapphire-paratime'; -import { Asset, DDO } from '@oceanprotocol/ddo-js'; +import { Asset, DDO, DDOManager } from '@oceanprotocol/ddo-js'; import { AccesslistFactory, Aquarius, Nft, @@ -118,7 +118,6 @@ export async function createAssetUtil( accessListFactory?: string, allowAccessList?: string, denyAccessList?: string, - ) { const isAddress = typeof templateIDorAddress === 'string' const isTemplateIndex = typeof templateIDorAddress === 'number' @@ -159,10 +158,12 @@ export async function updateAssetMetadata( let flags; let metadata; const validateResult = await aquariusInstance.validate(updatedDdo, owner, oceanNodeUrl); + const ddoInstance = DDOManager.getDDOClass(updatedDdo); + const { chainId, nftAddress } = ddoInstance.getDDOFields(); if (encryptDDO) { const providerResponse = await ProviderInstance.encrypt( updatedDdo, - updatedDdo.chainId, + chainId, oceanNodeUrl, owner ); @@ -177,7 +178,7 @@ export async function updateAssetMetadata( } const updateDdoTX = await nft.setMetadata( - updatedDdo.nftAddress, + nftAddress, await owner.getAddress(), 0, oceanNodeUrl, @@ -202,9 +203,9 @@ export async function handleComputeOrder( consumeMarkerFee?: ConsumeMarketFee ) { /* We do have 3 possible situations: - - have validOrder and no providerFees -> then order is valid, providerFees are valid, just use it in startCompute - - have validOrder and providerFees -> then order is valid but providerFees are not valid, we need to call reuseOrder and pay only providerFees - - no validOrder -> we need to call startOrder, to pay 1 DT & providerFees + - have validOrder and no providerFees -> then order is valid, providerFees are valid, just use it in startCompute + - have validOrder and providerFees -> then order is valid but providerFees are not valid, we need to call reuseOrder and pay only providerFees + - no validOrder -> we need to call startOrder, to pay 1 DT & providerFees */ const hasProviderFees = order.providerFee && order.providerFee.providerFeeAmount // no need to approve if it is 0 @@ -257,7 +258,9 @@ export async function isOrderable( algorithm: ComputeAlgorithm, algorithmDDO: Asset | DDO ): Promise { - const datasetService = asset.services.find((s) => s.id === serviceId); + const ddoInstanceAsset = DDOManager.getDDOClass(asset); + const { services: servicesAsset } = ddoInstanceAsset.getDDOFields(); + const datasetService = servicesAsset.find((s) => s.id === serviceId); if (!datasetService) return false; if (datasetService.type === "compute") { @@ -418,4 +421,4 @@ export async function getConfigByChainId(chainId: number) { } return chainConfig; -} \ No newline at end of file +} diff --git a/src/policyServerHelper.ts b/src/policyServerHelper.ts new file mode 100644 index 0000000..7127adb --- /dev/null +++ b/src/policyServerHelper.ts @@ -0,0 +1,418 @@ +import { Asset } from "@oceanprotocol/ddo-js" +import { PolicyServerActions, PolicyServerGetPdAction, PolicyServerInitiateAction, PolicyServerInitiateActionData, PolicyServerInitiateComputeActionData, PolicyServerPresentationDefinition, SsiVerifiableCredential, SsiWalletDid, SsiWalletSession } from "./policyServerInterfaces" +import axios from "axios" +import { Signer } from "ethers" + +export async function connectToSSIWallet( + owner: Signer, + api: string +): Promise { + if (!api) { + throw new Error('No SSI Wallet API configured') + } + + try { + let response = await axios.get(`${api}/wallet-api/auth/account/web3/nonce`) + + const nonce = response.data + const payload = { + challenge: nonce, + signed: await owner.signMessage(nonce), + publicKey: await owner.getAddress() + } + + response = await axios.post( + `${api}/wallet-api/auth/account/web3/signed`, + payload + ) + return response.data + } catch (error) { + throw error.response + } +} + +export async function sendPresentationRequest( + walletId: string, + did: string, + presentationRequest: string, + selectedCredentials: string[], + token: string, + api: string +): Promise<{ redirectUri: string }> { + if (!api) { + throw new Error('No SSI Wallet API configured') + } + try { + const response = await axios.post( + `${api}/wallet-api/wallet/${walletId}/exchange/usePresentationRequest`, + { + did, + presentationRequest, + selectedCredentials + }, + { + headers: { + Authorization: `Bearer ${token}` + }, + withCredentials: true + } + ) + + return response.data + } catch (error) { + throw error.response + } +} + +export async function resolvePresentationRequest( + walletId: string, + presentationRequest: string, + token: string, + api: string +): Promise { + if (!api) { + throw new Error('No SSI Wallet API configured') + } + try { + const response = await axios.post( + `${api}/wallet-api/wallet/${walletId}/exchange/resolvePresentationRequest`, + presentationRequest, + { + headers: { + Authorization: `Bearer ${token}` + }, + withCredentials: true + } + ) + + return response.data + } catch (error) { + throw error.response + } +} + +export async function getWalletDids( + walletId: string, + token: string, + api: string +): Promise { + if (!api) { + throw new Error('No SSI Wallet API configured') + } + try { + const response = await axios.get( + `${api}/wallet-api/wallet/${walletId}/dids`, + { + headers: { + Authorization: `Bearer ${token}` + }, + withCredentials: true + } + ) + + return response.data + } catch (error) { + throw error.response + } +} + + +export async function requestCredentialPresentation( + asset: Asset, + consumerAddress: string, + serviceId: string, + providerUrl: string +): Promise<{ + success: boolean + openid4vc: string + policyServerData: PolicyServerInitiateActionData, +}> { + try { + const sessionId = crypto.randomUUID() + + const policyServer: PolicyServerInitiateActionData = { + sessionId, + successRedirectUri: ``, + errorRedirectUri: ``, + responseRedirectUri: ``, + presentationDefinitionUri: `` + } + + const action: PolicyServerInitiateAction = { + action: PolicyServerActions.INITIATE, + ddo: asset, + policyServer, + serviceId, + consumerAddress, + documentId: asset.id + } + const response = await axios.post( + `${providerUrl}/api/services/PolicyServerPassthrough`, + { + policyServerPassthrough: action + } + ) + + if (response.data.length === 0) { + // eslint-disable-next-line no-throw-literal + throw { success: false, message: 'No openid4vc url found' } + } + + return { + success: response.data?.success, + openid4vc: response.data?.message, + policyServerData: policyServer + } + } catch (error) { + if (error.request?.response) { + const err = JSON.parse(error.request.response) + throw err + } + if (error.response?.data) { + throw error.response?.data + } + throw error + } +} + +export async function matchCredentialForPresentationDefinition( + api: string, + walletId: string, + presentationDefinition: any, + token: string +): Promise { + if (!api) { + throw new Error('No SSI Wallet API configured') + } + try { + const response = await axios.post( + `${api}/wallet-api/wallet/${walletId}/exchange/matchCredentialsForPresentationDefinition`, + presentationDefinition, + { + headers: { + Authorization: `Bearer ${token}` + }, + withCredentials: true + } + ) + + return response.data + } catch (error) { + throw error.response + } +} + +export async function getPd( + sessionId: string, + providerUrl: string +): Promise { + try { + const action: PolicyServerGetPdAction = { + action: PolicyServerActions.GET_PD, + sessionId + } + const response = await axios.post( + `${providerUrl}/api/services/PolicyServerPassthrough`, + { + policyServerPassthrough: action + } + ) + + if (typeof response.data === 'string' && response.data.length === 0) { + // eslint-disable-next-line no-throw-literal + throw { + success: false, + message: 'Could not read presentation definition' + } + } + + return response.data?.message + } catch (error) { + if (error.response?.data) { + throw error.response?.data + } + throw error + } +} + +export function extractURLSearchParams( + urlString: string +): Record { + const url = new URL(urlString) + const { searchParams } = url + const params: Record = {} + searchParams.forEach((value, key) => (params[key] = value)) + return params +} + +export async function getPolicyServerOBJ( + ddo: Asset, + serviceId: string, + signer: Signer, + providerUrl: string +): Promise { + try { + const accountId = await signer.getAddress() + const presentationResult = await requestCredentialPresentation( + ddo, + accountId, + serviceId, + providerUrl + ) + if ( + !presentationResult.openid4vc || + !presentationResult.success || + !presentationResult.policyServerData.sessionId + ) { + throw new Error('No valid openid4vc url found') + } + if ( + presentationResult.openid4vc && + typeof presentationResult.openid4vc === 'object' && + (presentationResult.openid4vc as any).redirectUri && + (presentationResult.openid4vc as any).redirectUri.includes( + 'success' + ) + ) { + const { id } = extractURLSearchParams( + (presentationResult.openid4vc as any).redirectUri + ) + return { + sessionId: id, + successRedirectUri: '', + errorRedirectUri: '', + responseRedirectUri: '', + presentationDefinitionUri: '' + } + } + const verifierSessionId = presentationResult.policyServerData.sessionId + + const presentationDefinition = await getPd(verifierSessionId, providerUrl) + const ssiApi = process.env.SSI_WALLET_API + if (!ssiApi) { + throw new Error('No SSI_WALLET_API configured') + } + const sessionToken = await connectToSSIWallet(signer, ssiApi) + const walletId = process.env.SSI_WALLET_ID + if (!walletId) { + throw new Error('No SSI_WALLET_ID configured') + } + const verifiableCredentials = await matchCredentialForPresentationDefinition( + ssiApi, + walletId, + presentationDefinition, + sessionToken.token + ) + const dids = await getWalletDids( + walletId, + sessionToken.token, + ssiApi + ) + if (!dids || dids.length === 0) { + throw new Error('No DIDs found in wallet') + } + const resolvedPresentationRequest = await resolvePresentationRequest( + walletId, + presentationResult.openid4vc, + sessionToken.token, + ssiApi + ) + const myDid = process.env.SSI_WALLET_DID + if (myDid && !dids.find((d) => d.did === myDid)) { + throw new Error(`DID ${myDid} not found in wallet`) + } + const did = myDid ? myDid : dids[0].did + const result = await sendPresentationRequest( + walletId, + did, + resolvedPresentationRequest, + verifiableCredentials.map((vc) => vc.id), + sessionToken.token, + ssiApi + ) + if ( + 'errorMessage' in result || + (result.redirectUri && result.redirectUri.includes('error')) + ) { + throw new Error('Credential presentation failed') + } + return { + sessionId: verifierSessionId, + successRedirectUri: '', + errorRedirectUri: '', + responseRedirectUri: '', + presentationDefinitionUri: '' + } + } catch (error: any) { + console.error('getPolicyServerOBJ error:', error) + if (error?.message) { + throw new Error(`getPolicyServerOBJ failed: ${error.message}`) + } + throw new Error('getPolicyServerOBJ failed') + } +} + +export async function getPolicyServerOBJs( + ddos: { + documentId: string + serviceId: string + asset: Asset + version?: string + }[], + algo: { + documentId: string + serviceId: string + asset: Asset + version?: string + }, + signer: Signer, + providerUrl: string +): Promise { + try { + const results: PolicyServerInitiateComputeActionData[] = [] + + // --- datasets + for (const ddo of ddos) { + if (!ddo.version || ddo.version < '5.0.0') { + return null + } + const result = await getPolicyServerOBJ( + ddo.asset, + ddo.serviceId, + signer, + providerUrl + ) + results.push({ + ...result, + documentId: ddo.documentId, + serviceId: ddo.serviceId + }) + } + + // --- algo + if (!algo?.version || algo.version < '5.0.0') { + return null + } + if (algo.serviceId) { + const algoResult = await getPolicyServerOBJ( + algo.asset, + algo.serviceId, + signer, + providerUrl + ) + results.push({ + ...algoResult, + documentId: algo.documentId, + serviceId: algo.serviceId + }) + } + + return results + } catch (error: any) { + console.error('getPolicyServerOBJs error:', error) + if (error?.message) { + throw new Error(`getPolicyServerOBJs failed: ${error.message}`) + } + throw new Error('getPolicyServerOBJs failed') + } +} diff --git a/src/policyServerInterfaces.ts b/src/policyServerInterfaces.ts new file mode 100644 index 0000000..99a44f0 --- /dev/null +++ b/src/policyServerInterfaces.ts @@ -0,0 +1,105 @@ +export interface SsiWalletSession { + session_id: string + status: string + token: string + expiration: Date +} + +export interface SsiVerifiableCredential { + id: string + parsedDocument: { + id: string + type: string[] + issuer: string + issuanceDate: Date + credentialSubject: Record + } +} + +export interface SsiWalletDid { + alias: string + did: string + document: string + keyId: string +} + +export enum PolicyServerActions { + INITIATE = 'initiate', + GET_PD = 'getPD', + CHECK_SESSION_ID = 'checkSessionId', + PRESENTATION_REQUEST = 'presentationRequest', + DOWNLOAD = 'download', + PASSTHROUGH = 'passthrough' +} + +export interface PolicyServerResponse { + success: boolean + message: string + httpStatus: number +} + +export interface PolicyServerInitiateActionData { + sessionId: string + successRedirectUri: string + errorRedirectUri: string + responseRedirectUri: string + presentationDefinitionUri: string +} + +export interface PolicyServerInitiateComputeActionData + extends PolicyServerInitiateActionData { + documentId: string + serviceId: string +} + + +export interface PolicyServerInitiateComputeActionData + extends PolicyServerInitiateActionData { + documentId: string + serviceId: string +} + +export interface PolicyServerInitiateAction { + action: PolicyServerActions.INITIATE + ddo: any + policyServer: PolicyServerInitiateActionData + serviceId: string + consumerAddress: string + documentId: string +} + +export interface PolicyServerGetPdAction { + action: PolicyServerActions.GET_PD + sessionId: string +} + +export interface PolicyServerCheckSessionIdAction { + action: PolicyServerActions.CHECK_SESSION_ID + sessionId: string +} + +export interface PolicyServerPresentationRequestAction { + action: PolicyServerActions.PRESENTATION_REQUEST + sessionId: string + vp_token: any + response: any + presentation_submission: any +} + +export interface PolicyServerDownloadAction { + action: PolicyServerActions.DOWNLOAD + policyServer: { + sessionId: string + } +} + +export interface PolicyServerPassthrough { + action: PolicyServerActions.PASSTHROUGH + url: string + httpMethod: 'GET' + body: any +} + +export interface PolicyServerPresentationDefinition { + input_descriptors: any[] +} diff --git a/test/consumeFlow.test.ts b/test/consumeFlow.test.ts index 94545c5..cf43690 100644 --- a/test/consumeFlow.test.ts +++ b/test/consumeFlow.test.ts @@ -6,7 +6,7 @@ import https from "https"; import { projectRoot, runCommand } from "./util.js"; -describe("Ocean CLI Publishing", function() { +describe("Ocean CLI Publishing", function () { this.timeout(200000); // Set a longer timeout to allow the command to execute let downloadDatasetDid: string; @@ -36,9 +36,9 @@ describe("Ocean CLI Publishing", function() { }); }); }; - - it("should publish a dataset using 'npm run cli publish'", async function() { + + it("should publish a dataset using 'npm run cli publish'", async function () { const metadataFile = path.resolve(projectRoot, "metadata/simpleDownloadDataset.json"); // Ensure the metadata file exists @@ -54,22 +54,44 @@ describe("Ocean CLI Publishing", function() { const output = await runCommand(`npm run cli publish ${metadataFile}`); - const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); + const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find did in the output"); - } + console.error("Raw output:", output); + throw new Error("Could not find did in the output"); + } - try { - downloadDatasetDid = jsonMatch[0]; - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + try { + downloadDatasetDid = jsonMatch[0]; + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should publish a compute dataset using 'npm run cli publish'", async function() { + it("should publish a dataset v5 using 'npm run cli publish'", async function () { + const metadataFile = path.resolve(projectRoot, "metadata/simpleDownloadDatasetV5.json"); + + // Ensure the metadata file exists + if (!fs.existsSync(metadataFile)) { + throw new Error("Metadata file not found: " + metadataFile); + } + + process.env.PRIVATE_KEY = "0x1d751ded5a32226054cd2e71261039b65afb9ee1c746d055dd699b1150a5befc"; + // Using this account: 0x529043886F21D9bc1AE0feDb751e34265a246e47 + process.env.RPC = "http://127.0.0.1:8545"; + process.env.NODE_URL = "http://127.0.0.1:8001"; + process.env.ADDRESS_FILE = path.join(process.env.HOME || "", ".ocean/ocean-contracts/artifacts/address.json"); + + const output = await runCommand(`npm run cli publish ${metadataFile}`); + const jsonMatch = output.match(/did:ope:[a-f0-9]{64}/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find did in the output"); + } + }); + + it("should publish a compute dataset using 'npm run cli publish'", async function () { const metadataFile = path.resolve(projectRoot, "metadata/simpleComputeDataset.json"); // Ensure the metadata file exists if (!fs.existsSync(metadataFile)) { @@ -78,44 +100,44 @@ describe("Ocean CLI Publishing", function() { const output = await runCommand(`npm run cli publish ${metadataFile}`); - const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); + const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find did in the output"); - } - - try { - computeDatasetDid = jsonMatch[0]; - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + console.error("Raw output:", output); + throw new Error("Could not find did in the output"); + } + + try { + computeDatasetDid = jsonMatch[0]; + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should publish a js Algorithm using 'npm run cli publishAlgo'", async function() { + it("should publish a js Algorithm using 'npm run cli publishAlgo'", async function () { const filePath = path.resolve(projectRoot, "metadata/jsAlgo.json"); // Ensure the metadata file exists if (!fs.existsSync(filePath)) { throw new Error("Metadata file not found: " + filePath); } - + const output = await runCommand(`npm run cli publishAlgo ${filePath}`); const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find did in the output"); - } - - try { - jsAlgoDid = jsonMatch[0]; - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + console.error("Raw output:", output); + throw new Error("Could not find did in the output"); + } + + try { + jsAlgoDid = jsonMatch[0]; + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should publish a python Algorithm using 'npm run cli publishAlgo'", async function() { + it("should publish a python Algorithm using 'npm run cli publishAlgo'", async function () { const filePath = path.resolve(projectRoot, "metadata/pythonAlgo.json"); // Ensure the metadata file exists @@ -126,91 +148,91 @@ describe("Ocean CLI Publishing", function() { const output = await runCommand(`npm run cli publishAlgo ${filePath}`); const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find did in the output"); - } - - try { - pythonAlgoDid = jsonMatch[0]; - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + console.error("Raw output:", output); + throw new Error("Could not find did in the output"); + } + + try { + pythonAlgoDid = jsonMatch[0]; + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get DDO using 'npm run cli getDDO' for download dataset", async function() { + it("should get DDO using 'npm run cli getDDO' for download dataset", async function () { const output = await runCommand(`npm run cli getDDO ${downloadDatasetDid}`); - const jsonMatch = output.match(/s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find ddo in the output"); - } + const jsonMatch = output.match(/s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find ddo in the output"); + } try { expect(output).to.contain(`Resolving Asset with DID: ${downloadDatasetDid}`) - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get DDO using 'npm run cli getDDO' for compute dataset", async function() { + it("should get DDO using 'npm run cli getDDO' for compute dataset", async function () { const output = await runCommand(`npm run cli getDDO ${computeDatasetDid}`); - const jsonMatch = output.match(/s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find ddo in the output"); - } + const jsonMatch = output.match(/s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find ddo in the output"); + } try { expect(output).to.contain(`Resolving Asset with DID: ${computeDatasetDid}`) - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get DDO using 'npm run cli getDDO' for JS algorithm", async function() { + it("should get DDO using 'npm run cli getDDO' for JS algorithm", async function () { const output = await runCommand(`npm run cli getDDO ${jsAlgoDid}`); - const jsonMatch = output.match(/s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find ddo in the output"); - } + const jsonMatch = output.match(/s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find ddo in the output"); + } try { - expect(output).to.contain(`Resolving Asset with DID: ${jsAlgoDid}`) - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + expect(output).to.contain(`Resolving Asset with DID: ${jsAlgoDid}`) + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get DDO using 'npm run cli getDDO' for python algorithm", async function() { + it("should get DDO using 'npm run cli getDDO' for python algorithm", async function () { const output = await runCommand(`npm run cli getDDO ${pythonAlgoDid}`); - const jsonMatch = output.match(/s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find ddo in the output"); - } + const jsonMatch = output.match(/s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find ddo in the output"); + } try { - expect(output).to.contain(`Resolving Asset with DID: ${pythonAlgoDid}`) - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + expect(output).to.contain(`Resolving Asset with DID: ${pythonAlgoDid}`) + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should download the download dataset", async function() { + it("should download the download dataset", async function () { this.timeout(10000); // Increase timeout if needed const output = await runCommand(`npm run cli download ${downloadDatasetDid} .`); - + expect(output).to.contain("File downloaded successfully"); // Path to the downloaded file @@ -227,6 +249,6 @@ describe("Ocean CLI Publishing", function() { // Clean up downloaded original file fs.unlinkSync(originalFilePath); - + }); }); diff --git a/test/interactivePublishFlow.ts b/test/interactivePublishFlow.ts index b8cd82e..9c238a2 100644 --- a/test/interactivePublishFlow.ts +++ b/test/interactivePublishFlow.ts @@ -7,13 +7,13 @@ import { fileURLToPath } from 'url' const __filename = fileURLToPath(import.meta.url) const __dirname = dirname(__filename) -describe("Ocean CLI Interactive Publishing", function() { +describe("Ocean CLI Interactive Publishing", function () { this.timeout(120000); // Set a longer timeout to allow for user input simulation const projectRoot = path.resolve(__dirname, ".."); let publishedDid: string; - it("should publish an asset using 'npm run cli start' interactive flow", function(done) { + it("should publish an asset using 'npm run cli start' interactive flow", function (done) { process.env.PRIVATE_KEY = "0x1d751ded5a32226054cd2e71261039b65afb9ee1c746d055dd699b1150a5befc"; process.env.RPC = "http://127.0.0.1:8545"; process.env.NODE_URL = "http://127.0.0.1:8001"; @@ -43,7 +43,9 @@ describe("Ocean CLI Interactive Publishing", function() { if (child.stdin) { const inputInterval = setInterval(() => { if (inputIndex < inputs.length) { - child.stdin.write(inputs[inputIndex]); + if (child.stdin) { + child.stdin.write(inputs[inputIndex]); + } inputIndex++; } else { clearInterval(inputInterval); @@ -61,7 +63,7 @@ describe("Ocean CLI Interactive Publishing", function() { expect(code).to.equal(0); expect(fullOutput).to.contain("Asset successfully published with DID:"); expect(fullOutput).to.contain("Metadata successfully updated for DID:"); - + const match = fullOutput.match(/did:op:[a-f0-9]{64}/); if (match) { publishedDid = match[0]; @@ -77,7 +79,7 @@ describe("Ocean CLI Interactive Publishing", function() { }); }); - it("should get DDO using 'npm run cli getDDO' for the published asset", function(done) { + it("should get DDO using 'npm run cli getDDO' for the published asset", function (done) { exec(`npm run cli getDDO ${publishedDid}`, { cwd: projectRoot }, (error, stdout) => { try { expect(stdout).to.contain(`${publishedDid}`); diff --git a/test/paidComputeFlow.test.ts b/test/paidComputeFlow.test.ts index 8847cb3..e3b0799 100644 --- a/test/paidComputeFlow.test.ts +++ b/test/paidComputeFlow.test.ts @@ -3,13 +3,13 @@ import path from "path"; import fs from "fs"; import { homedir } from 'os' import { - ProviderInstance + ProviderInstance } from "@oceanprotocol/lib"; import { projectRoot, runCommand } from "./util.js"; -describe("Ocean CLI Paid Compute", function() { +describe("Ocean CLI Paid Compute", function () { this.timeout(600000); // Set a longer timeout to allow the command to execute let computeDatasetDid: string; @@ -23,15 +23,15 @@ describe("Ocean CLI Paid Compute", function() { const getAddresses = () => { const data = JSON.parse( fs.readFileSync( - process.env.ADDRESS_FILE || + process.env.ADDRESS_FILE || `${homedir}/.ocean/ocean-contracts/artifacts/address.json`, - 'utf8' + 'utf8' ) ) return data.development }; - it("should publish a compute dataset using 'npm run cli publish'", async function() { + it("should publish a compute dataset using 'npm run cli publish'", async function () { const metadataFile = path.resolve(projectRoot, "metadata/simpleComputeDataset.json"); // Ensure the metadata file exists if (!fs.existsSync(metadataFile)) { @@ -46,21 +46,21 @@ describe("Ocean CLI Paid Compute", function() { const output = await runCommand(`npm run cli publish ${metadataFile}`); - const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); + const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find compute dataset did in the output"); - } - - try { - computeDatasetDid = jsonMatch[0]; - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + console.error("Raw output:", output); + throw new Error("Could not find compute dataset did in the output"); + } + + try { + computeDatasetDid = jsonMatch[0]; + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should publish a js Algorithm using 'npm run cli publishAlgo'", async function() { + it("should publish a js Algorithm using 'npm run cli publishAlgo'", async function () { const filePath = path.resolve(projectRoot, "metadata/jsAlgo.json"); // Ensure the metadata file exists @@ -70,92 +70,94 @@ describe("Ocean CLI Paid Compute", function() { const output = await runCommand(`npm run cli publishAlgo ${filePath}`); - const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find algo did in the output"); - } + const jsonMatch = output.match(/did:op:[a-f0-9]{64}/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find algo did in the output"); + } try { - jsAlgoDid = jsonMatch[0]; - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + jsAlgoDid = jsonMatch[0]; + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get DDO using 'npm run cli getDDO' for compute dataset", async function() { + it("should get DDO using 'npm run cli getDDO' for compute dataset", async function () { const output = await runCommand(`npm run cli getDDO ${computeDatasetDid}`); - const jsonMatch = output.match(/s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find ddo in the output"); - } + const jsonMatch = output.match(/s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find ddo in the output"); + } try { expect(output).to.contain(`Resolving Asset with DID: ${computeDatasetDid}`) - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get DDO using 'npm run cli getDDO' for JS algorithm", async function() { + it("should get DDO using 'npm run cli getDDO' for JS algorithm", async function () { const output = await runCommand(`npm run cli getDDO ${jsAlgoDid}`); - const jsonMatch = output.match(/s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find ddo in the output"); - } + const jsonMatch = output.match(/s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find ddo in the output"); + } try { - expect(output).to.contain(`Resolving Asset with DID: ${jsAlgoDid}`) - } catch (error) { - console.error("Extracted output:", jsonMatch[0]); - throw new Error("Failed to parse the extracted output:\n" + error); - } + expect(output).to.contain(`Resolving Asset with DID: ${jsAlgoDid}`) + } catch (error) { + console.error("Extracted output:", jsonMatch[0]); + throw new Error("Failed to parse the extracted output:\n" + error); + } }); - it("should get compute environments using 'npm run cli getComputeEnvironments'", async function() { + it("should get compute environments using 'npm run cli getComputeEnvironments'", async function () { const output = await runCommand(`npm run cli getComputeEnvironments`); - const jsonMatch = output.match(/Exiting compute environments:\s*([\s\S]*)/); - if (!jsonMatch) { - console.error("Raw output:", output); - throw new Error("Could not find compute environments in the output"); - } - - let environments; - try { - environments = eval(jsonMatch[1]); - } catch (error) { - console.error(`Extracted output: ${jsonMatch[0]} and final result: ${jsonMatch[1]}`); - throw new Error("Failed to parse the extracted output:\n" + error); - } - - expect(environments).to.be.an("array").that.is.not.empty; - - const firstEnv = environments[0]; - - expect(firstEnv).to.have.property("id").that.is.a("string"); - expect(firstEnv).to.have.property("consumerAddress").that.is.a("string"); - expect(firstEnv).to.have.property("resources").that.is.an("array"); - - computeEnvId = firstEnv.id; - - console.log(`Fetched Compute Env ID: ${computeEnvId}`); + const jsonMatch = output.match(/Exiting compute environments:\s*([\s\S]*)/); + if (!jsonMatch) { + console.error("Raw output:", output); + throw new Error("Could not find compute environments in the output"); + } + + let environments; + try { + environments = eval(jsonMatch[1]); + } catch (error) { + console.error(`Extracted output: ${jsonMatch[0]} and final result: ${jsonMatch[1]}`); + throw new Error("Failed to parse the extracted output:\n" + error); + } + + expect(environments).to.be.an("array").that.is.not.empty; + + const firstEnv = environments[0]; + + expect(firstEnv).to.have.property("id").that.is.a("string"); + expect(firstEnv).to.have.property("consumerAddress").that.is.a("string"); + expect(firstEnv).to.have.property("resources").that.is.an("array"); + + computeEnvId = firstEnv.id; + + console.log(`Fetched Compute Env ID: ${computeEnvId}`); }); - it("should start paid compute on compute dataset and algorithm", async function() { + it("should start paid compute on compute dataset and algorithm with services id for dataset and algorithm", async function () { const computeEnvs = await ProviderInstance.getComputeEnvironments('http://127.0.0.1:8001'); const env = computeEnvs[0]; expect(env).to.be.an('object').and.to.not.be.null.and.to.not.be.undefined; resources = [] const paymentToken = getAddresses().Ocean - const output = await runCommand(`npm run cli -- startCompute ${computeDatasetDid} ${jsAlgoDid} ${computeEnvId} 900 ${paymentToken} '${JSON.stringify(resources)}' --accept true`); + const serviceIdDataset = 'ccb398c50d6abd5b456e8d7242bd856a1767a890b537c2f8c10ba8b8a10e6025' + const serviceIdAlgorithm = 'db164c1b981e4d2974e90e61bda121512e6909c1035c908d68933ae4cfaba6b0' + const output = await runCommand(`npm run cli -- startCompute ${computeDatasetDid} ${jsAlgoDid} ${computeEnvId} 900 ${paymentToken} '${JSON.stringify(resources)}' ${serviceIdDataset} ${serviceIdAlgorithm} --accept true`); const jobIdMatch = output.match(/JobID:\s*([^\s]+)/); const agreementIdMatch = output.match(/Agreement ID:\s*([^\s]+)/); @@ -194,24 +196,24 @@ describe("Ocean CLI Paid Compute", function() { }).timeout(10200) it("should get job status", async () => { - const output = await runCommand(`npm run cli getJobStatus ${computeDatasetDid} ${computeJobId} ''`); - expect(output).to.contain(computeJobId); - expect(output.toLowerCase()).to.match(/status/); - console.log(`Job status retrieved for jobId: ${computeJobId}`); - }); + const output = await runCommand(`npm run cli getJobStatus ${computeDatasetDid} ${computeJobId} ''`); + expect(output).to.contain(computeJobId); + expect(output.toLowerCase()).to.match(/status/); + console.log(`Job status retrieved for jobId: ${computeJobId}`); + }); - it("should download compute job results", async () => { - const destFolder = path.join(projectRoot, "test-results", computeJobId); - fs.mkdirSync(destFolder, { recursive: true }); + it("should download compute job results", async () => { + const destFolder = path.join(projectRoot, "test-results", computeJobId); + fs.mkdirSync(destFolder, { recursive: true }); - const output = await runCommand(`npm run cli downloadJobResults ${computeJobId} 1 ${destFolder}`); + const output = await runCommand(`npm run cli downloadJobResults ${computeJobId} 1 ${destFolder}`); - expect(output.toLowerCase()).to.match(/download(ed)?/); + expect(output.toLowerCase()).to.match(/download(ed)?/); - const files = fs.readdirSync(destFolder); - expect(files.length).to.be.greaterThan(0, "No result files downloaded"); - console.log(`Downloaded results to: ${destFolder}`); + const files = fs.readdirSync(destFolder); + expect(files.length).to.be.greaterThan(0, "No result files downloaded"); + console.log(`Downloaded results to: ${destFolder}`); fs.rmSync(path.join(projectRoot, "test-results"), { recursive: true }) - }); - + }); + }); diff --git a/test/setup.test.ts b/test/setup.test.ts index 8702483..c0452c6 100644 --- a/test/setup.test.ts +++ b/test/setup.test.ts @@ -42,7 +42,7 @@ describe("Ocean CLI Setup", function() { expect(stdout).to.contain("Starts a FREE compute job"); expect(stdout).to.contain("stopCompute [options] "); expect(stdout).to.contain("Stops a compute job"); - expect(stdout).to.contain("getJobStatus [options] "); + expect(stdout).to.contain("getJobStatus [options] [agreementId]"); expect(stdout).to.contain("Displays the compute job status"); expect(stdout).to.contain("downloadJobResults [destinationFolder]"); expect(stdout).to.contain("Downloads compute job results");