{"id":18877559,"url":"https://github.com/nftstorage/ipnftx","last_synced_at":"2026-02-19T01:30:15.644Z","repository":{"id":50643724,"uuid":"400639570","full_name":"nftstorage/ipnftx","owner":"nftstorage","description":"***Notice: This repository is no longer maintained.*** InterPlanetary NFT Extensions (IPNFTX)","archived":false,"fork":false,"pushed_at":"2021-09-16T20:44:54.000Z","size":8,"stargazers_count":14,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-12-31T02:24:24.262Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nftstorage.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-27T21:31:47.000Z","updated_at":"2024-07-01T22:39:15.000Z","dependencies_parsed_at":"2022-08-28T13:21:31.461Z","dependency_job_id":null,"html_url":"https://github.com/nftstorage/ipnftx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nftstorage%2Fipnftx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nftstorage%2Fipnftx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nftstorage%2Fipnftx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nftstorage%2Fipnftx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nftstorage","download_url":"https://codeload.github.com/nftstorage/ipnftx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239837647,"owners_count":19705381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T06:20:01.858Z","updated_at":"2026-02-19T01:30:15.569Z","avatar_url":"https://github.com/nftstorage.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- # Non-Fungible Token Description Framework (NFT-DF) --\u003e\n\n# InterPlanetary NFT Extensions (IPNFTX)\n\n\n## Simple Summary\n\nA standard interface for non-fungible token _overlay_ data, expressed as a set of statements in form of `(entity, attribute, value)` tuples. \n\n## Abstract\n\nThe following standard allows for the implementation of a standard API for providing _overlay data_ for NFTs within smart contracts. This standard provides a basic functionality for publishing, tracking and indexing information associated with NFTs.\n\n\u003e Just as anyone can make statements about things in the physical world we aim to enable any actor on the network to make statements about specific NFTs on blockchain, regardless of their owner or contract origin. Just as in physical world individuals choose who's statements to consider any actors can choose which sources (contracts) and on what subject (attribute) to track / index.\n\nWe consider use case for NFTs in which they are entities that anyone on the network (regardless of their ownership) can publish statements about in form of (entity, attribute, value) forming open informational graph of [entity, attribute, values][EAV] similar to [RDF][]. Of course, the contract/owner of an NFT can use this protocol to provide data about their own NFT's, but the system is not limited to this in the same way that anyone on the Web can link to any website.\n\nWe aim at enable additional layers of functionality on top NFTs in an open ended, yet interoperable manner with little to no coordination.\n\n## Motivation\n\nA standard interface for overlay data for NFTs  allows extending NFTs in manner which:\n\n1. Upholds NFTs immutablity guarantees. \n2. Allow arbitrary actors to extend NFTs.\n3. Protocol Extensions require little or no coordination (multiformats).\n4. Protocol Extensions are interoperable (multiformats) / conflict-free (append-only onchain events).\n\n\nThis standard is inspired by [Datomic Data Model][] and [Resource Description Framework (RDF)][RDF].\n\n#### Examples\n\n##### Associating CID with NFT\n\nhttps://nft.storage service archives NFT assets on IPFS \u0026 filecoin, yet there is no good way to associate those [CID][]s to corresponding tokens.\n\n##### Preview images\n\nTODO: Scaled preview images for NFTs. \n\n##### IPNS\n\nTODO: Map NFT to a CID to represent mutable content\n\n## Specification\n\nThe 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.\n\n**Every NFT-AV contract must implement the NFTAV interface**\n\n```solidity\ninterface ERC721 {\n  /// Event adds or retracts relation between\n  ///   - entity (NFT identified by `contract address`,\n  ///     `uint256 tokenId` pair)\n  ///   - attribute (multiformat value describing a\n  ///     relation)\n  ///   - value (value for the attribute)\n  /// \n  /// A boolean `op` indicates whether relation is\n  /// added or retracted\n  event IPNFT(\n    uint256 source_id, // NFT tokenId\n    bytes entity, // multiformat MF(token_contract, token_id, net, chain)\n    bytes attribute, // multiformat MF(cardinality, type, ...rest:MF)\n    bytes value // multiformat CID or MF(RETRACT_OR_APPEND, CID)\n  );\n}\n```\n\nThe `IPNFT` events are associate with a source NFT in their contract. This event describes\ninformation about `entities`. When describeing information about *this* NFT the `entity` will be an empty (null) binary.\n\n\nIPNFT can be used to publish and interlink metadata about entities represented as NFTs. \n\nTODO\n\n## Indexing\n\nWe can create secure per-chain indexes of these events and roll all chains into a master index\nfor all of Web3. The events would look something like:\n\n```\n{ chainNamespace: 'eth',\n  chainReference: 'mainnet',\n  contractAddress: Binary,\n  transaction: Binary,\n  tokenId: 12987189739812,\n  source: 89879798,\n  entity: Binary,\n  attribute: Binary,\n  value: Binary\n}\n```\n\nNote that every event has a `transaction` id provided by the chain.\n\nYou can then imagine a REST interface that caches access to this information to make it easily\navailable to web developers.\n\n```\n/ipnft/eth/mainnet/{contractAddress}/{tokenId}/{entity}/{attribute}\n```\n\nWhen the values are CID's we can do everything we do from gateways using these mutable identifiers.\n\n```\n/ipnft/eth/mainnet/{contractAddress}/{tokenId}/{entity}/{attribute}/_latest?format=jpeg\n/ipnft/eth/mainnet/{contractAddress}/{tokenId}/{entity}/{attribute}/_latest?format=car\n```\n\nWe can put the last transaction in a header so that you can query its history since a previous state.\n\n```\n/nftx/eth/mainnet/{contractAddress}/{tokenId}/{entity}/{attribute}/_since?transaction={transaction}\n```\n\nThis would allow any number of new database to be written since this effectively globalizes a\ncache of the change feed of any database written to this protocol, without these gateways\neven needing to be aware of the underlying database protocol.\n\n## Rationale\n\nTODO\n\n## The OPTIONAL description protocol extension\n\nEach `IPNFT` event is a fact / statement that represent addition or retraction of a relation between an **entity**, an **attribute** and a **value**. This forms triples graph where `entity` denotes the resource (usually NFT in some chain), and the `attribute` denotes traits or aspects of the _entity_, and expresses a relation between the `entity` and a the `value`.\n\n\u003e While some indexes can choose to unify set of statements across (some or all) sources _(that are globally identifiable by `contract`, `source_id` pair)_, others may choose to namespace by a `contract` or `source_id` or both.\n\u003e \n\u003e This allows both interoperability before standardisation and extensiblity without breaking compatiblity.\n\n### Entity\n\nAn entity denotes the subject about which statement are made.\n\nWhen `subject` is empty (0 bytes) it is considered to refec to the `source` token itself (as in `(emitting_contract, source)` pair). This is convinient when contract want to make statements about its own tokens.\n\nHowever `subject` may encode information about other tokens, even in other chains. It is adviced to encode this information in [multiformat][]:\n\n- **chain** - blockchain identifier\n- **network** - network identifier, mainnet, testnet, etc...\n- **contract** - contract address that issued token\n- **token_id** - token identifier\n\n// TODO: this should be a generic multiformat for identifying NFT's, similar to what ceramic and did do.\n\n### Attributes\n\nEvery attribute is identified by a [multiformat][] value that follows (TCS+) (cardinality, type, subject) encodes it's semantics:\n\n- **Cardinality**, specifying whether NFTs can have one or a set of values for the attribute.\n- **Type**, the type allowed for an attribute's value. That is one of the following types:\n    - boolean\n    - integer\n    - float\n    - string\n    - bytes\n    - link\n- **Predicate**, specifying rest of relation semantics. This can be just an arbitrary name or multiformat encoding more domain semantics.\n\n\n\n### Attribute Values\n\nNFT Attribute Values MUST be [multiformat][] \nthat encode following:\n\n- **OP** - Retraction or Addtion\n- **Data** - Value that MUST correspond to the an attribute type. If attribute type is _link_ data MUST be a valid [CID][].\n\n### References\n\n- [Datoms][] from datomic\n- [Resource Description Framework (RDF)][rdf]\n- [InterPlanetary Name System (IPNS)][IPNS]\n- [ERC-721]\n- [multiformat]\n- [did:key]\n- [IPLD]\n- [EAV]\n- [CID]\n\n### Notes\n\n\n\n[did:key]:https://w3c-ccg.github.io/did-method-key/\n[datoms]:https://docs.datomic.com/cloud/whatis/data-model.html#datoms\n[rdf]:https://en.wikipedia.org/wiki/Resource_Description_Framework\n[IPNS]:https://docs.ipfs.io/concepts/ipns/\n[ERC-721]:https://eips.ethereum.org/EIPS/eip-721\n[multiformat]:https://multiformats.io/\n[UCAN]:https://whitepaper.fission.codes/access-control/cap-authz\n[IPLD]:https://github.com/ipld/specs/blob/master/data-model-layer/data-model.md\n[EAV]:https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model\n[CID]:https://docs.ipfs.io/concepts/content-addressing/\n[Datomic Data Model]:https://docs.datomic.com/cloud/whatis/data-model.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnftstorage%2Fipnftx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnftstorage%2Fipnftx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnftstorage%2Fipnftx/lists"}