diff --git a/.github/workflows/schema_validation.yml b/.github/workflows/schema_validation.yml new file mode 100644 index 0000000..d1f5b56 --- /dev/null +++ b/.github/workflows/schema_validation.yml @@ -0,0 +1,28 @@ +name: Schema Validation + +on: + pull_request: + paths: + - "EVES/**/example/*.json" + - "EVES/**/*-schemas/*.json" + - "package.json" + +jobs: + validate: + name: Validate Examples Against Schemas + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Setup Node + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: "22" + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Validate schemas + run: npm run validate:schemas diff --git a/.prettierignore b/.prettierignore index 9014560..2cec42d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ node_modules/ EVES/EVES-003/example/ EVES/EVES-003/tzip21-schemas/ +EVES/EVES-003/erc721-schemas/ .github/styles/ *.zip diff --git a/EVES/EVES-003/erc721-schemas/erc721_token_metadata-schema.json b/EVES/EVES-003/erc721-schemas/erc721_token_metadata-schema.json new file mode 100644 index 0000000..9a42f11 --- /dev/null +++ b/EVES/EVES-003/erc721-schemas/erc721_token_metadata-schema.json @@ -0,0 +1,210 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "EVES-003 profile of ERC-721 token metadata. Base fields (name, description, image) from the ERC-721 Metadata JSON Schema (EIP-721). Display fields (animation_url, external_url, background_color, attributes) from OpenSea Metadata Standards (de facto, no upstream schema). EVES extension fields (minter, creators, contributors, publishers, date, type, language, rights, rights_uri, identifier, formats) mirror TZIP-21 for cross-chain interoperability.", + "$ref": "#/definitions/asset", + "definitions": { + "asset": { + "title": "ERC-721 Token Metadata (EVES-003 Profile)", + "type": "object", + "additionalProperties": true, + "required": [ + "name", + "image" + ], + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents." + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents." + }, + "image": { + "type": "string", + "format": "uri-reference", + "description": "A URI pointing to a resource with mime type image/* representing the asset. Maps to TZIP-21 displayUri." + }, + "animation_url": { + "type": "string", + "format": "uri-reference", + "description": "A URI pointing to the actual asset content (for example, asset.zip download URL). Maps to TZIP-21 artifactUri." + }, + "external_url": { + "type": "string", + "format": "uri-reference", + "description": "A URI pointing to an external page with additional information about the asset (for example, domain metadata on IPFS). Maps to TZIP-21 externalUri." + }, + "background_color": { + "type": "string", + "pattern": "^[0-9a-fA-F]{6}$", + "description": "Background color of the item on OpenSea. Must be a six-character hexadecimal without a pre-pended #." + }, + "minter": { + "type": "string", + "description": "The DID of the LegalEntity (OrganizationParticipant) responsible for minting the asset, as defined in EVES-008 (for example, did:ethr::
). EVES extension." + }, + "creators": { + "type": "array", + "description": "The primary person, people, or organization(s) responsible for creating the intellectual content of the asset.", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "contributors": { + "type": "array", + "description": "The person, people, or organization(s) that have made substantial creative contributions to the asset.", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "publishers": { + "type": "array", + "description": "The person, people, or organization(s) primarily responsible for distributing or making the asset available to others in its present form.", + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "date": { + "type": "string", + "format": "date-time", + "description": "A date associated with the creation or availability of the asset." + }, + "type": { + "type": "string", + "description": "A broad definition of the type of content of the asset." + }, + "language": { + "type": "string", + "description": "The language of the intellectual content of the asset as defined in RFC 1766. EVES extension." + }, + "rights": { + "type": "string", + "description": "A statement about the asset rights, for example, an SPDX license identifier." + }, + "rights_uri": { + "type": "string", + "format": "uri-reference", + "description": "Links to a statement of rights (for example, full license text or smart contract DID). Maps to TZIP-21 rightsUri. EVES extension." + }, + "identifier": { + "type": "string", + "description": "A string or number used to uniquely identify the asset. Ex. URL, URN, UUID, ISBN, DID, etc." + }, + "formats": { + "type": "array", + "items": { + "$ref": "#/definitions/format" + } + }, + "attributes": { + "type": "array", + "items": { + "$ref": "#/definitions/attribute" + }, + "description": "OpenSea-style attributes describing traits of the asset." + } + } + }, + "format": { + "type": "object", + "additionalProperties": false, + "properties": { + "uri": { + "type": "string", + "format": "uri-reference", + "description": "A URI to the asset represented in this format." + }, + "hash": { + "type": "string", + "description": "A checksum hash of the content of the asset in this format." + }, + "mimeType": { + "type": "string", + "description": "Media (MIME) type of the format." + }, + "fileSize": { + "type": "integer", + "description": "Size in bytes of the content of the asset in this format." + }, + "fileName": { + "type": "string", + "description": "Filename for the asset in this format. For display purposes." + }, + "duration": { + "type": "string", + "format": "time", + "description": "Time duration of the content of the asset in this format." + }, + "dimensions": { + "$ref": "#/definitions/dimensions", + "description": "Dimensions of the content of the asset in this format." + }, + "dataRate": { + "$ref": "#/definitions/dataRate", + "description": "Data rate which the content of the asset in this format was captured at." + } + } + }, + "attribute": { + "type": "object", + "additionalProperties": false, + "properties": { + "trait_type": { + "type": "string", + "description": "Name of the trait." + }, + "value": { + "description": "Value of the trait.", + "oneOf": [ + { "type": "string" }, + { "type": "number" } + ] + }, + "display_type": { + "type": "string", + "description": "Display type hint for the trait (for example, number, boost_percentage, boost_number, date)." + } + }, + "required": [ + "trait_type", + "value" + ] + }, + "dataRate": { + "type": "object", + "additionalProperties": false, + "properties": { + "value": { + "type": "integer" + }, + "unit": { + "type": "string" + } + }, + "required": [ + "unit", + "value" + ] + }, + "dimensions": { + "type": "object", + "additionalProperties": false, + "properties": { + "value": { + "type": "string" + }, + "unit": { + "type": "string" + } + }, + "required": [ + "unit", + "value" + ] + } + } +} diff --git a/EVES/EVES-003/eves-003.md b/EVES/EVES-003/eves-003.md index c7f8638..5be4ad5 100644 --- a/EVES/EVES-003/eves-003.md +++ b/EVES/EVES-003/eves-003.md @@ -6,14 +6,15 @@ discussions-to: https://github.com/ASCS-eV/EVES/issues/4 status: Review type: Standards created: 2024-11-19 -requires: ["EVES-001"] +requires: ["EVES-001", "EVES-007", "EVES-008"] replaces: None --- ## Abstract This specification defines the structure of an asset in the ENVITED-X Data Space and outlines the process for uploading assets to ensure compliance, security, and interoperability. -It leverages existing specifications, such as the Gaia-X Trust Framework, the Gaia-X 4 PLC-AAD Ontologies, and implements privacy layers, validation, and metadata mapping aligned with [Tezos TZIP-21](https://docs.tezos.com/architecture/governance/improvement-process#tzip-21-rich-contract-metadata). +It leverages existing specifications, such as the Gaia-X Trust Framework, the ENVITED-X Ontologies, and implements privacy layers, validation, and metadata mapping aligned with +[Tezos TZIP-21](https://docs.tezos.com/architecture/governance/improvement-process#tzip-21-rich-contract-metadata) and [ERC-721][26] token metadata following the [OpenSea Metadata Standards][23]. ## Motivation @@ -27,13 +28,15 @@ This EVES addresses the need for clear guidelines to onboard assets and synchron ## Specification +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119][16]. + ### 1. Digital Asset Definition The `envited-x:SimulationAsset` defines a digital asset within the domain of simulation including the core simulation data and all necessary files for describing, evaluating, and visualizing the dataset. -All simulation assets MUST be derived from a common `envited-x` ontology defined in the [Gaia-X 4 PLC-AAD Ontology Management Base][1]. -A data space portal SHALL display the currently supported version of the ontologies such as: `https://ontologies.envited-x.net/envited-x/v2/ontology#`. +All simulation assets MUST be derived from a common `envited-x` ontology defined in the [ASCS Ontology Management Base][1]. +A data space portal SHALL display the currently supported version of the ontologies such as: `https://w3id.org/ascs-ev/envited-x/envited-x/v3/`. Each simulation asset SHALL be compliant with the [Gaia-X Ontology and SHACL shapes 2210][2]. -The `gx` turtle shacle shapes are derived from the [Gaia-X Trust Framework Schema][3] and the respective application/ld+json [Gaia-X Trust Framework Shapes][4]. +The `gx` turtle SHACL shapes are derived from the [Gaia-X Trust Framework Schema][3] and the respective application/ld+json [Gaia-X Trust Framework Shapes][4]. A [GaiaX Compliant Claims Example][5] MAY be generated using the [GaiaX 4 PLC-AAD Claim Compliance Provider][6]. The example implementation in the 📁 `example/` folder is based on release v0.2.3 of the [ASCS HD-Map Asset Example][7]. @@ -198,7 +201,9 @@ The following process is implemented in the [ENVITED-X Data Space][12] portal de - Create `envited-x_manifest.json` by replacing relative paths in `manifest_reference.json` with IPFS/envited-x.net URLs. - Replace the paths of items in `hasReferencedArtifacts` to the correct filePaths. - Replace `@id` from `manifest_reference.json` with generated database `UUID` in `envited-x_manifest.json`. This also applies for referenced artifacts. -- Create `tzip21_token_metadata.json` and map the metadata fields OPTIONALLY use an application/ld+json conform to the [tzip21 ontology][19]. +- Create the chain-specific token metadata file and map the metadata fields: + - **Tezos (TZIP-21):** Create `tzip21_token_metadata.json` OPTIONALLY conforming to the [tzip21 ontology][19] as application/ld+json. + - **EVM (ERC-721):** Create `erc721_token_metadata.json` following the [OpenSea Metadata Standards][23]. #### Step 3: Preview Data @@ -210,8 +215,12 @@ The following process is implemented in the [ENVITED-X Data Space][12] portal de - It is RECOMMENDED to use signed CIDs for the upload to IPFS according to [EIP-712][13]. - Upload `isPublic` information and `envited-x_manifest.json` to IPFS. - It is RECOMMENDED to verify that CIDs from the IPFS service or software returns the same CIDs as the pre-calculation. -- Upload `tzip21_token_metadata.json` to IPFS. -- Mint token with linked metadata. +- Upload the chain-specific token metadata file to IPFS: + - **Tezos:** Upload `tzip21_token_metadata.json`. + - **EVM:** Upload `erc721_token_metadata.json`. +- Mint token with linked metadata: + - **Tezos:** Mint an FA2.1 token with the TZIP-21 metadata URI as the token metadata. + - **EVM:** Mint an [ERC-721][26] token where `tokenURI()` resolves to the ERC-721 metadata JSON on IPFS. The contract SHOULD implement [ERC-5192][25] for soulbound (non-transferable) tokens if applicable. The contract SHOULD emit [ERC-4906][24] `MetadataUpdate` events when metadata changes. - The wallet/SDK will provide feedback if a token was minted successfully. #### Step 5: Listener and Database Synchronization @@ -219,9 +228,9 @@ The following process is implemented in the [ENVITED-X Data Space][12] portal de - Use a listener to detect mint events and synchronize data with the ENVITED-X Data Space portal database. - A data space like the ENVITED-X Data Space MUST check if the asset was uploaded through its respective portal: - `UUID` from step 2) has an entry in the database. - - Confirm that `contract` + `CID` and `minter` of tzip21_token_metadata.json are the same as in the database. + - Confirm that `contract` + `CID` and `minter` of the token metadata file (`tzip21_token_metadata.json` or `erc721_token_metadata.json`) are the same as in the database. - Confirm that the entries `UUID` and `@id` of the asset are unique. - - OPTIONALLY check if the EIP-712 signature of the tzip21_token_metadata.json matches the user who initiated the mint (SHALL only be known to the respective portal). + - OPTIONALLY check if the EIP-712 signature of the token metadata file matches the user who initiated the mint (SHALL only be known to the respective portal). - If the asset is not yet in DB OPTIONALLY mark it as foreign asset and add the `publisher` information to the DB. - It is RECOMMENDED to verify the asset in reverse order as in step 1). - Only public information of assets can be verified if uploaded through another portal than ENVITED-X data space. @@ -231,7 +240,7 @@ The following process is implemented in the [ENVITED-X Data Space][12] portal de #### @id and CID as the Primary Identifier - The CID of the uploaded `asset.zip` serves as the unique identifier detecting identical datasets across all systems. -- In addition the unique identifier `@id` of the `envied-x:SimulationAsset` in the `domainMetadata.json` SHALL be used for identification of the digital assets. +- In addition the unique identifier `@id` of the `envited-x:SimulationAsset` in the `domainMetadata.json` SHALL be used for identification of the digital assets. - The CIDs MAY be signed by the user according to EIP-712. - A UUID MUST be generated for the `envited-x_manifest.json` pre-mint to link the asset with the ENVITED-X database securely. - The DID of the member associated with the user minting the asset MUST be known. @@ -246,37 +255,113 @@ If additional non-public information needs to be stored in the database before m [EVES-007](../EVES-007/eves-007.md) defines the ENVITED-X Blockchain Identifier URN Schema. The synchronization between the smart contract as in the [Marketplace Contract Reference Implementation][18] and the ENVITED-X database relies on: -1. The contract identifier on Tezos (current Ghostnet contract): - `urn:blockchain:tezos:NetXnHfVqm9iesp:contract:KT1PCaD2kmgCHy15wQ1gpqZUy9RLxyBVJdTF` -2. Search `CID` of `tzip21_token_metadata.json` and the complete `asset.zip` in database. +1. The contract identifier using the [EVES-007](../EVES-007/eves-007.md) URN schema: + - **Tezos** (current Ghostnet contract): + `urn:blockchain:tezos:NetXnHfVqm9iesp:contract:KT1PCaD2kmgCHy15wQ1gpqZUy9RLxyBVJdTF` + - **EVM** (Etherlink L2): + `urn:blockchain:eip155:42793:contract:0x646B92C8f21e55DF67E766047E4bD7bEdF8DfA14` +2. Search `CID` of the token metadata file (`tzip21_token_metadata.json` or `erc721_token_metadata.json`) and the complete `asset.zip` in database. 3. Compare if signature on CID is a `user` belonging to the `member` and if member is owner of token. 4. Check: Uniqueness of CID in database. -### TZIP-21 Token Metadata +### 6. Token Metadata + + + +This section defines how EVES-003 asset metadata is mapped to chain-specific token metadata formats. +The core EVES-003 fields (derived from the ENVITED-X manifest and domain metadata) are identical regardless of target chain; only the serialization format differs. + +The minter MUST be a `simpulseid:OrganizationParticipant` (LegalEntity) identified by their `did:ethr` DID as defined in [EVES-008][28]. +The `did:ethr` identifier is anchored on Base (ERC-1056) and serves as the cross-chain organizational identity regardless of the target minting chain (Tezos or EVM). +The natural person performing the mint is linked to the organization through the `memberOf` credential property. -#### TZIP-21 Rich Metadata Mapping +#### TZIP-21 Rich Metadata (Tezos) Attributes not in the table are static and the same for every mint as in the 📁 `example/tzip21_token_metadata.json`. Examples are the first five tags or "publishers", which is always ENVITED-X and the ASCS if the mint is conducted through the [website][12]. -| TZIP-21 | EVES-003 | Comment | -| ------------- | -------------------------------------------------------- | -------------------------------------------------------------------------- | -| "name" | envited-x:DataResource:gx:name | | -| "description" | envited-x:DataResource:gx:description | | -| "tags" | $TAG = format:formatType + " " + format:version | "tags": ["GaiaX","ASCS","ENVITED-X","EVES","nft", "$TAG"] | -| "minter" | Member DID (CAIP-10) associated with user | Returned by the View from the SimpulseID revocation registry | -| "creators" | Name of the company | Taken from the company profile the user belongs to | -| "date" | [System date-time][14] | | -| "rights" | manifest:hasLicense:gx:license | [SPDX identifier][15] | -| "rightsUri" | manifest:hasLicense:licenseData:hasFileMetadata:filePath | Full os license text URL OR policy smart contract did | -| "artifactUri" | | | -| "identifier" | Simulation Asset @id | Unique identifier from the domainMetadata.json | -| "externalUri" | Uploaded domainMetadata.json to IPFS | | -| "displayUri" | "manifest:hasArtifacts:Link" of category "isMedia" | Always use the first media image | -| "formats" | artifactUri, externalUri, displayUri, envited-x_manifest | | -| "attributes" | Reverse domain notation for ontologies + URL | All ontologies from top level nodes in files referenced in formats section | - -**>Note:** Some of the information need to be extracted from the `gx:LegalParticipant`. +| TZIP-21 | EVES-003 | Comment | +| ------------- | --------------------------------------------------------- | ------------------------------------------------------------------ | +| "name" | envited-x:hasResourceDescription → gx:name | | +| "description" | envited-x:hasResourceDescription → gx:description | | +| "tags" | $TAG = format:formatType + " " + format:version | "tags": ["GaiaX","ASCS","ENVITED-X","EVES","nft", "$TAG"] | +| "minter" | LegalEntity DID from [EVES-008][28] | did:ethr:\:\ of the OrganizationParticipant | +| "creators" | Name of the company | Taken from the company profile the user belongs to | +| "date" | [System date-time][14] | | +| "language" | Language of the asset content | [RFC 1766][29] language tag | +| "rights" | envited-x:hasResourceDescription → gx:license | [SPDX identifier][15] | +| "rightsUri" | manifest:hasLicense → manifest:hasFileMetadata → filePath | Full license text URL OR policy smart contract DID | +| "artifactUri" | | | +| "identifier" | Simulation Asset @id | Unique identifier from the domainMetadata.json | +| "externalUri" | Uploaded domainMetadata.json to IPFS | | +| "displayUri" | manifest:hasArtifacts → Link of category "isMedia" | Always use the first media image | +| "formats" | artifactUri, externalUri, displayUri, envited-x_manifest | | +| "attributes" | Ontology IRI + version URL | Domain, ecosystem, Gaia-X, and georeference ontologies | + +> **Note:** Some of the information needs to be extracted from the `gx:LegalParticipant` via the SimpulseID `ParticipantCredential`. + +#### ERC-721 Metadata (EVM) + +ERC-721 token metadata follows the [OpenSea Metadata Standards][23] which extend the minimal [ERC-721][26] `tokenURI()` JSON schema with additional fields. +Attributes not in the table are static and the same for every mint as in the 📁 `example/erc721_token_metadata.json`. + +| ERC-721 / OpenSea | EVES-003 | Comment | +| ------------------ | --------------------------------------------------------- | ------------------------------------------------------------------- | +| "name" | envited-x:hasResourceDescription → gx:name | | +| "description" | envited-x:hasResourceDescription → gx:description | | +| "image" | manifest:hasArtifacts → Link of category "isMedia" | Always use the first media image. Maps to TZIP-21 "displayUri" | +| "animation_url" | | Maps to TZIP-21 "artifactUri" | +| "external_url" | Uploaded domainMetadata.json to IPFS | Maps to TZIP-21 "externalUri" | +| "background_color" | ENVITED-X brand background color | Six-character hex without `#` (OpenSea standard) | +| "attributes" | Tags + ontology attributes as trait_type/value pairs | See mapping note below | +| "minter" | LegalEntity DID from [EVES-008][28] | did:ethr:\:\ (EVES extension) | +| "creators" | Name of the company | Taken from the company profile (EVES extension) | +| "contributors" | Contributing persons or organizations | (EVES extension) | +| "publishers" | Name of the publishing organizations | (EVES extension) | +| "date" | [System date-time][14] | (EVES extension) | +| "type" | "EVES-003" + EVES URL | (EVES extension) | +| "language" | Language of the asset content | [RFC 1766][29] language tag (EVES extension) | +| "rights" | envited-x:hasResourceDescription → gx:license | [SPDX identifier][15] (EVES extension) | +| "rights_uri" | manifest:hasLicense → manifest:hasFileMetadata → filePath | Full license text URL OR policy smart contract DID (EVES extension) | +| "identifier" | Simulation Asset @id | Unique identifier from the domainMetadata.json (EVES extension) | +| "formats" | artifactUri, externalUri, displayUri, envited-x_manifest | (EVES extension, same structure as TZIP-21) | + +**Attributes mapping note:** TZIP-21 uses a flat `"tags"` string array and a separate `"attributes"` array with `name`/`value`/`type` objects. +In ERC-721, both are merged into the OpenSea-style `"attributes"` array using `"trait_type"`/`"value"` objects. +Each TZIP-21 tag becomes an attribute (for example, `{"trait_type": "Format", "value": "ASAM OpenDRIVE 1.6"}`), +and each TZIP-21 attribute's `name`/`value` maps directly to `trait_type`/`value` +(for example, `{"trait_type": "https://w3id.org/ascs-ev/envited-x/hdmap/v6/", "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6"}`). +Using the full ontology IRI as `trait_type` ensures each attribute is unique and machine-parseable; the `type` field from TZIP-21 is omitted as it has no OpenSea equivalent. + +**Ontology attributes:** The attributes section SHOULD include all ontologies that the asset instance conforms to. +For an HD-Map asset, the following ontology attributes are RECOMMENDED: + +- **Domain ontology** (for example, `hdmap/v6`): identifies the simulation asset type +- **Ecosystem ontology** (`envited-x/v3`): identifies the asset as part of the ENVITED-X Data Space +- **Gaia-X ontology** (`gx`): signals conformance with the Gaia-X Trust Framework for data space interoperability +- **Georeference ontology** (`georeference/v5`): included when the asset contains geospatial reference data (OPTIONAL per the [hdmap SHACL shapes][21]) + +The `value` for each ontology attribute SHOULD be the release URL of the [ASCS Ontology Management Base][1] version used, except for `gx` which references the [Gaia-X Policy Rules Compliance Document][17]. + +> **Note:** Fields marked as "(EVES extension)" are not part of the base ERC-721 or OpenSea standard but are defined by EVES-003 +> for interoperability with the ENVITED-X Data Space. +> Marketplaces will display `name`, `description`, `image`, `animation_url`, `external_url`, and `attributes` natively; +> EVES extension fields are consumed by the ENVITED-X portal. + +#### ERC-7572 Contract-Level Metadata (EVM) + +For EVM-based deployments, the marketplace contract SHOULD implement [ERC-7572][27] by exposing a `contractURI()` function +that returns a URI to a JSON document describing the contract/collection. +This has no TZIP-21 equivalent as Tezos handles collection-level metadata differently through FA2.1 contract storage. + +The `contractURI()` response SHOULD include at minimum: + +- `name`: the collection name (for example, "ENVITED-X Simulation Assets") +- `description`: a description of the collection +- `image`: a collection image/logo URI +- `external_link`: URL to the ENVITED-X Data Space portal + +The contract SHOULD emit a `ContractURIUpdated()` event as defined in [ERC-7572][27] when the contract-level metadata is changed. #### Custom SPDX license identifier @@ -287,6 +372,8 @@ Examples are the first five tags or "publishers", which is always ENVITED-X and This specification introduces new processes for asset uploads and is fully compatible with existing ENVITED-X systems. No retroactive changes to previous assets are required. +The addition of EVM/ERC-721 support is additive and does not alter the existing Tezos/TZIP-21 metadata path. +Existing assets minted on Tezos remain valid without modification. ## Future Improvements @@ -315,6 +402,13 @@ The compatibility with the current release of the [Gaia-X Policy Rules Complianc - [ENVITED-X Simulation Asset Tools][20] - [ENVITED-X Ontology][21] - [Manifest Ontology][22] +- [OpenSea Metadata Standards][23] +- [ERC-4906: EIP-721 Metadata Update Extension][24] +- [ERC-5192: Minimal Soulbound NFTs][25] +- [ERC-721: Non-Fungible Token Standard][26] +- [ERC-7572: Contract-Level Metadata via contractURI()][27] +- [EVES-008: ENVITED-X Identity and Credential Framework][28] +- [RFC 1766: Tags for the Identification of Languages][29] [1]: https://github.com/ASCS-eV/ontology-management-base/ [2]: https://github.com/ASCS-eV/ontology-management-base/tree/main/artifacts/gx @@ -338,3 +432,10 @@ The compatibility with the current release of the [Gaia-X Policy Rules Complianc [20]: https://github.com/openMSL/sl-5-8-asset-tools [21]: https://github.com/ASCS-eV/ontology-management-base/tree/main/artifacts/envited-x [22]: https://github.com/ASCS-eV/ontology-management-base/tree/main/artifacts/manifest +[23]: https://docs.opensea.io/docs/metadata-standards +[24]: https://eips.ethereum.org/EIPS/eip-4906 +[25]: https://eips.ethereum.org/EIPS/eip-5192 +[26]: https://eips.ethereum.org/EIPS/eip-721 +[27]: https://eips.ethereum.org/EIPS/eip-7572 +[28]: ../EVES-008/eves-008.md +[29]: https://datatracker.ietf.org/doc/html/rfc1766 diff --git a/EVES/EVES-003/example/envited-x_manifest.json b/EVES/EVES-003/example/envited-x_manifest.json index 568d366..f8a4a58 100644 --- a/EVES/EVES-003/example/envited-x_manifest.json +++ b/EVES/EVES-003/example/envited-x_manifest.json @@ -1,13 +1,14 @@ { - "@context": { - "envited-x": "https://ontologies.envited-x.net/envited-x/v2/ontology#", - "manifest": "https://ontologies.envited-x.net/manifest/v4/ontology#", - "gx": "https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#", - "sh": "http://www.w3.org/ns/shacl#", - "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - "skos": "http://www.w3.org/2004/02/skos/core#" - }, + "@context": [ + "https://w3id.org/ascs-ev/envited-x/manifest/v5/", + { + "envited-x": "https://w3id.org/ascs-ev/envited-x/envited-x/v3/", + "gx": "https://w3id.org/gaia-x/development#", + "skos": "http://www.w3.org/2004/02/skos/core#", + "sh": "http://www.w3.org/ns/shacl#", + "xsd": "http://www.w3.org/2001/XMLSchema#" + } + ], "@id": "urn:uuid:896f0b9d-5626-4ddb-9d28-568f4af63603", "@type": "envited-x:Manifest", "manifest:hasManifestReference": { @@ -33,30 +34,27 @@ } }, "manifest:hasLicense": { - "@type": "manifest:License", - "gx:license": { - "@value": "MPL-2.0" + "@type": "manifest:Link", + "manifest:iri": { + "@id": "https://www.mozilla.org/en-US/MPL/2.0/" }, - "manifest:licenseData": { - "@type": "manifest:Link", - "manifest:hasAccessRole": { - "@type": "manifest:AccessRole", - "@id": "envited-x:isPublic" - }, - "manifest:hasCategory": { - "@type": "manifest:Category", - "@id": "envited-x:isLicense" + "manifest:hasAccessRole": { + "@type": "manifest:AccessRole", + "@id": "envited-x:isPublic" + }, + "manifest:hasCategory": { + "@type": "manifest:Category", + "@id": "envited-x:isLicense" + }, + "manifest:hasFileMetadata": { + "@type": "manifest:FileMetadata", + "manifest:filePath": { + "@value": "https://www.mozilla.org/en-US/MPL/2.0/", + "@type": "xsd:anyURI" }, - "manifest:hasFileMetadata": { - "@type": "manifest:FileMetadata", - "manifest:filePath": { - "@value": "https://www.mozilla.org/en-US/MPL/2.0/", - "@type": "xsd:anyURI" - }, - "manifest:mimeType": { - "@value": "text/html", - "@type": "xsd:string" - } + "manifest:mimeType": { + "@value": "text/html", + "@type": "xsd:string" } } }, @@ -192,7 +190,7 @@ }, "sh:conformsTo": [ { - "@id": "https://ontologies.envited-x.net/hdmap/v3/ontology" + "@id": "https://w3id.org/ascs-ev/envited-x/hdmap/v6/" } ], "manifest:hasAccessRole": { diff --git a/EVES/EVES-003/example/erc721_token_metadata.json b/EVES/EVES-003/example/erc721_token_metadata.json new file mode 100644 index 0000000..785a31b --- /dev/null +++ b/EVES/EVES-003/example/erc721_token_metadata.json @@ -0,0 +1,105 @@ +{ + "name": "TestfeldNiedersachsen_ALKS_ODR_sample", + "description": "simple hdmap example file on Testfeld Niedersachsen for ALKS scenario", + "image": "ipfs://bafybeief5r2xgciehzhx6c4kbooifsnbjpiifjei36lpi3kzcdmpr2wvue", + "animation_url": "https://assets.envited-x.net/bafybeifo6ve5i6542vi6ruuflxdqtcmcisdtwlqefq2e5a33tljsaqxhpm", + "external_url": "ipfs://bafkreicuwg3s4uvei2iu2p5eobozghdodtwhwoi6qiawhwqj3nflrk6dxi", + "background_color": "111827", + "attributes": [ + { + "trait_type": "Standard", + "value": "GaiaX" + }, + { + "trait_type": "Publisher", + "value": "ASCS" + }, + { + "trait_type": "Ecosystem", + "value": "ENVITED-X" + }, + { + "trait_type": "Specification", + "value": "EVES" + }, + { + "trait_type": "Token Type", + "value": "nft" + }, + { + "trait_type": "Format", + "value": "ASAM OpenDRIVE 1.6" + }, + { + "trait_type": "https://w3id.org/ascs-ev/envited-x/hdmap/v6/", + "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6" + }, + { + "trait_type": "https://w3id.org/ascs-ev/envited-x/envited-x/v3/", + "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6" + }, + { + "trait_type": "https://w3id.org/gaia-x/development#", + "value": "https://docs.gaia-x.eu/policy-rules-committee/compliance-document/24.11/" + }, + { + "trait_type": "https://w3id.org/ascs-ev/envited-x/georeference/v5/", + "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6" + } + ], + "minter": "did:ethr:0x14a34:0x50916c8e454722d2357916d4250500102288bb03", + "creators": [ + "Automotive Solution Center for Simulation e.V." + ], + "publishers": [ + "Automotive Solution Center for Simulation e.V.", + "ENVITED-X Data Space" + ], + "date": "2025-02-17T00:00:00+00:00", + "type": "EVES-003 https://github.com/ASCS-eV/EVES", + "language": "en", + "rights": "MPL-2.0", + "rights_uri": "https://www.mozilla.org/en-US/MPL/2.0/", + "identifier": "did:web:registry.gaia-x.eu:HdMap:DjHgK5ErTBow1Ya3J05tW9l12skGWgZn6kA9", + "formats": [ + { + "uri": "https://assets.envited-x.net/bafybeifo6ve5i6542vi6ruuflxdqtcmcisdtwlqefq2e5a33tljsaqxhpm", + "hash": "bafybeifo6ve5i6542vi6ruuflxdqtcmcisdtwlqefq2e5a33tljsaqxhpm", + "mimeType": "application/zip", + "fileSize": 7711664, + "fileName": "Testfeld_Niedersachsen_ALKS_xodr_sample.zip" + }, + { + "uri": "ipfs://bafkreicuwg3s4uvei2iu2p5eobozghdodtwhwoi6qiawhwqj3nflrk6dxi", + "hash": "bafkreicuwg3s4uvei2iu2p5eobozghdodtwhwoi6qiawhwqj3nflrk6dxi", + "mimeType": "application/ld+json", + "fileSize": 6574, + "fileName": "hdmap_instance.json" + }, + { + "uri": "ipfs://bafkreigxkhnuuyjrb2nyduivdaqbrbuw7zcjf6aaslvlufvmgv5bfsh6u4", + "hash": "bafkreigxkhnuuyjrb2nyduivdaqbrbuw7zcjf6aaslvlufvmgv5bfsh6u4", + "mimeType": "application/ld+json", + "fileSize": 21630, + "fileName": "manifest_reference.json" + }, + { + "uri": "ipfs://bafkreie2yjoudxlayordup63se7wbj6vroaoyqzcuixqcchpmd23ufno6u", + "hash": "bafkreie2yjoudxlayordup63se7wbj6vroaoyqzcuixqcchpmd23ufno6u", + "mimeType": "application/ld+json", + "fileSize": 5572, + "fileName": "envited-x_manifest.json" + }, + { + "uri": "ipfs://bafybeief5r2xgciehzhx6c4kbooifsnbjpiifjei36lpi3kzcdmpr2wvue", + "hash": "bafybeief5r2xgciehzhx6c4kbooifsnbjpiifjei36lpi3kzcdmpr2wvue", + "mimeType": "image/png", + "dimensions": { + "value": "1095x850", + "unit": "px" + }, + "fileSize": 2397906, + "fileName": "Testfeld_Niedersachsen_ALKS_..._impression-01.png" + } + ] +} diff --git a/EVES/EVES-003/example/tzip21_token_metadata.json b/EVES/EVES-003/example/tzip21_token_metadata.json index bf3b760..2b7b709 100644 --- a/EVES/EVES-003/example/tzip21_token_metadata.json +++ b/EVES/EVES-003/example/tzip21_token_metadata.json @@ -11,7 +11,7 @@ "nft", "ASAM OpenDRIVE 1.6" ], - "minter": "did:pkh:tezos:NetXnHfVqm9iesp:tz1cZaiTjNSN7x4VZjTQGYBVz4p8eEcVcYkz", + "minter": "did:ethr:0x14a34:0x50916c8e454722d2357916d4250500102288bb03", "creators": [ "Automotive Solution Center for Simulation e.V." ], @@ -71,13 +71,23 @@ ], "attributes": [ { - "name": "https://ontologies.envited-x.net/hdmap/v4/ontology#", - "value": "https://github.com/GAIA-X4PLC-AAD/ontology-management-base/releases/tag/v0.0.4", + "name": "https://w3id.org/ascs-ev/envited-x/hdmap/v6/", + "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6", "type": "uri" }, { - "name": "https://ontologies.envited-x.net/envited-x/v2/ontology#", - "value": "https://github.com/GAIA-X4PLC-AAD/ontology-management-base/releases/tag/v0.0.4", + "name": "https://w3id.org/ascs-ev/envited-x/envited-x/v3/", + "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6", + "type": "uri" + }, + { + "name": "https://w3id.org/gaia-x/development#", + "value": "https://docs.gaia-x.eu/policy-rules-committee/compliance-document/24.11/", + "type": "uri" + }, + { + "name": "https://w3id.org/ascs-ev/envited-x/georeference/v5/", + "value": "https://github.com/ASCS-eV/ontology-management-base/releases/tag/v0.1.6", "type": "uri" } ] diff --git a/EVES/EVES-003/tzip21-schemas/tzip21_token_metadata-schema.json b/EVES/EVES-003/tzip21-schemas/tzip21_token_metadata-schema.json index c432f41..ce86727 100644 --- a/EVES/EVES-003/tzip21-schemas/tzip21_token_metadata-schema.json +++ b/EVES/EVES-003/tzip21-schemas/tzip21_token_metadata-schema.json @@ -1,11 +1,13 @@ { "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "EVES-003 profile of TZIP-21 Rich Metadata. Deviations from upstream (gitlab.com/tezos/tzip): minter uses DID per EVES-008 instead of tzaddress, name is required. Upstream bug fixes: title moved inside definition (draft-07 $ref ignores siblings), RFC 1776 typo corrected to RFC 1766.", "$ref": "#/definitions/asset", - "title": "Rich Metadata", "definitions": { "asset": { + "title": "TZIP-21 Rich Metadata (EVES-003 Profile)", "type": "object", "additionalProperties": true, + "required": ["name"], "properties": { "description": { "type": "string", @@ -13,8 +15,7 @@ }, "minter": { "type": "string", - "format": "tzaddress", - "description": "The tz address responsible for minting the asset." + "description": "The DID of the LegalEntity (OrganizationParticipant) responsible for minting the asset, as defined in EVES-008 (for example, did:ethr::
)." }, "creators": { "type": "array", @@ -72,7 +73,7 @@ "language": { "type": "string", "format": "https://tools.ietf.org/html/rfc1766", - "description": "The language of the intellectual content of the asset as defined in RFC 1776." + "description": "The language of the intellectual content of the asset as defined in RFC 1766." }, "identifier": { "type": "string", diff --git a/package-lock.json b/package-lock.json index 52dcac5..e588329 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,6 +6,8 @@ "": { "name": "eves-specs", "devDependencies": { + "ajv-cli": "^5.0.0", + "ajv-formats": "^3.0.1", "gray-matter": "^4.0.3", "markdownlint-cli": "^0.48.0", "prettier": "^3.5.0" @@ -42,6 +44,68 @@ "dev": true, "license": "MIT" }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0", + "fast-json-patch": "^2.0.0", + "glob": "^7.1.0", + "js-yaml": "^3.14.0", + "json-schema-migrate": "^2.0.0", + "json5": "^2.1.3", + "minimist": "^1.2.0" + }, + "bin": { + "ajv": "dist/index.js" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", @@ -131,6 +195,13 @@ "node": ">=20" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -237,6 +308,50 @@ "node": ">=0.10.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^2.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fast-json-patch/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -255,6 +370,13 @@ } } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, "node_modules/get-east-asian-width": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", @@ -268,6 +390,59 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "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": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -294,6 +469,25 @@ "node": ">= 4" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, "node_modules/ini": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", @@ -376,6 +570,36 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-schema-migrate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", + "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonc-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", @@ -1112,6 +1336,16 @@ "dev": true, "license": "MIT" }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -1132,6 +1366,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", @@ -1171,6 +1415,16 @@ "node": ">=6" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/run-con": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz", @@ -1300,6 +1554,13 @@ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true, "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" } } } diff --git a/package.json b/package.json index 59db96a..2007638 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,12 @@ "lint:links": "lychee --no-progress '**/*.md'", "lint:frontmatter": "node scripts/validate-frontmatter.mjs", "format": "prettier --write '**/*.md' '**/*.json' '**/*.yml' --ignore-path .prettierignore", - "format:check": "prettier --check '**/*.md' '**/*.json' '**/*.yml' --ignore-path .prettierignore" + "format:check": "prettier --check '**/*.md' '**/*.json' '**/*.yml' --ignore-path .prettierignore", + "validate:schemas": "ajv validate --strict=false -c ajv-formats -s EVES/EVES-003/tzip21-schemas/tzip21_token_metadata-schema.json -d EVES/EVES-003/example/tzip21_token_metadata.json && ajv validate --strict=false -c ajv-formats -s EVES/EVES-003/erc721-schemas/erc721_token_metadata-schema.json -d EVES/EVES-003/example/erc721_token_metadata.json" }, "devDependencies": { + "ajv-cli": "^5.0.0", + "ajv-formats": "^3.0.1", "gray-matter": "^4.0.3", "markdownlint-cli": "^0.48.0", "prettier": "^3.5.0"