Giter Site home page Giter Site logo

rmrk-spec's Introduction

RMRK.app Specification and Standards

This repository hosts standards for creating and interacting with RMRK.app NFTs.

There are two types of standards: entities and interactions. Entities are definitions for how a collection or NFT should be declared while being minted, so that tools can recognize them as valid. Interactions are interactions between the off-chain world and the RMRK protocol, between those NFTs, and between different users and NFTs.

Interactions

The standards currently cover the following basic interactions:

  • MINT creates a new collection
  • MINTNFT creates a new NFT inside an existing collection
  • CONSUME burns an NFT
  • CHANGEISSUER changes the owner of the collection, affecting who can issue NFTs
  • SEND, BUY are transactional
  • LIST is used to list an NFT as for-sale on-chain
  • MIGRATE (starting with 1.0.0) allows a collection issuer to migrate a collection and its child NFTs to a new standard

Inspect each standard folder to see the specifics about these interactions and how to integrate them.

Entities

A collection of NFTs is an entity. An NFT inside a collection is an entity as well.

Releases

RMRK standards versions will be tagged as a release. Each release will contain all previous major and minor versions so that an implementer checking out the latest release can decide which ones to support alongside the latest.

A released version is never worked on again - all changes must happen via RIPs and will apply to the next version only. It is up to the implementing library / UI to see previous versions as invalid or demand a migration from an old version to a new version of an NFT (this will usually involve a CONSUME of an earlier NFT and a MINTNFT into a newer version of the collection) or a MIGRATE interaction. To be kept up to date on version changes, please Watch this repo or subscribe to Dot Leap or NFT Review.

Currently published standards:

Standards under development:

  • n/a

Contributing

To contribute, please create a new RIP (RMRK Improvement Proposal) as per this template.

Implementations

Interested in implementing these standards? Check out the Implementer's Guide.

The following is a list of implementations of these standards:

Extending the Standard

The RMRK standards will always support the very minimum of functionality needed to interact with NFTs. However, some projects may want or need more logic, or more specific integration. Let's say for example that someone is building a CryptoKitties game in which cats can "breed" to produce an offspring with some random on-chain attributes adding special uniqueness to the new cat token. The game devs would:

  • integrate with an implementation of RMRK
  • wrap RMRK functionality in their own library
  • define their own game's rules
  • MINT and do other interactions as per RMRK standards, but reacting to their custom rules

As an example, let's assume that we have a user who owns Cat A and Cat B and wants to breed them to get Cat C. Let's assume that breeding requires 100 blocks of time, and that a breeding results in an egg, this egg needs to incubate for 100 blocks, and then the user needs to manually hatch it.

To implement this, the CryptoKitties game devs would:

  • add a BREED and a HATCH interaction on top of the RMRK standards they already inherit through an implementation.
  • once BREED is called by a user, the starting block is logged (e.g. X).
  • at block X+100, the user can call HATCH and the egg hatches. The block hash is used as a seed for the random attributes of the new NFT.
  • a new NFT is created and assigned to the breeder.
  • given that the NFT is minted according to RMRK standards, it will be automatically compatible with any tools and UIs that follow the standard as well.

Note: A tricky part is step 4 - minting and assigning a new NFT to the breeder. This would require a new entity type given that only an issuer is allowed to mint new NFTs, but then the new entity is not automatically compatible with wallets and UIs following RMRK, given that they're not familiar with the CryptoKitties standard. This introduces a barrier to market entry for the CryptoKitties devs. A better alternative is skipping user-initiated hatching and hatching programmatically from CryptoKitties game devs' end, but this introduces a reliance on their service for the continuation of the game.

This is an active area of research which we hope to have ironed out soon - ideally with an action-triggered MINT addition to the standard.

Other Information

rmrk-spec's People

Contributors

bmacer avatar jeffanthony avatar swader avatar thunderdeliverer avatar vikiival avatar x676f64 avatar yuripetusko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rmrk-spec's Issues

rmrk-spec v1.0.0

is rmrk spec 1.0.0 the latest spec, i have an inkling there is a 2.0.0 somewhere but cannot find it?

About the name field in collection and nft entities

When using encodeURIComponent encoding, spaces will be encoded as %20. Do I need to deliberately replace %20 with +? Or should I not use the encodeURIComponent function to handle the encoding of html_encode_json, or is there another function to handle it?

Example

{
  "id": "0aff68d3a66b-DLEP",
  "name": "Dot Leap Early Promoters",
  "issuer": "CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp",
  "max": 100,
  "symbol": "DLEP",
  "version": "RMRK1.0.0",
  "metadata": "ipfs://ipfs/QmVgs8P4awhZpFXhkkgnCwBp4AdKRj3F9K58mCZ6fxvn3j"
}

Becomes:

rmrk::MINT::1.0.0::%7B%22id%22%3A%220aff68d3a66b-DLEP%22%2C%22name%22%3A%22Dot%20Leap%20Early%20Promoters%22%2C%22issuer%22%3A%22CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp%22%2C%22max%22%3A100%2C%22symbol%22%3A%22DLEP%22%2C%22version%22%3A%22RMRK1.0.0%22%2C%22metadata%22%3A%22ipfs%3A%2F%2Fipfs%2FQmVgs8P4awhZpFXhkkgnCwBp4AdKRj3F9K58mCZ6fxvn3j%22%7D

SETPRIORITY discrepancy between spec and rmrk-tools

There is a discrepancy between the RMRK2.0 standard for SETPRRIORITY and the implementation in rmrk-tools.

The spec is defined here: https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/setpriority.md

The example provided is this: rmrk::SETPRIORITY::2.0.0::5105000-0aff6865bed3a66b-DLEP-DL15-00000001::bar,foo,baz

Notice bar,foo,baz has no brackets or quotation marks.

However, in rmrk-tools, when you run the interaction for setpriority (example here: https://github.com/bmacer/rmrk2-interaction-examples/blob/master/interactions/setpriority/1-testing-setpriority.ts) the raw remark comes out like this:

RMRK::SETPRIORITY::2.0.0::11-ALICES_COLLECTION-ALICES_NFT-002::%5B%22bbbbb%22%2C%22aaaaa%22%5D

The relevant part is: %5B%22bbbbb%22%2C%22aaaaa%22%5D

URL decoded is: ["bbbbb","aaaaa"]

Notice there are brackets around the list and quotation marks around each item.

Essentially, either the rmrk-tools setpriority operation needs to be adjusted, or the example in the rmrk 2.0 spec needs to be updated.

I would expect the spec needs to be updated.

Discussion: private vs public collections

Allowing public to mint NFTs in one's collection: yay or nay? Flag which can be switched by owner of collection? Or wait for mainnet / Unique support for this.

Discuss.

Discussion: multi-resource NFTs

A common request is multi-resource NFTs.

We should come up with a standard which is backwards compatible with other NFT platforms like Unique or the internft.org standard, while at the same time allowing us to mint NFTs with multiple different resources like videos + thumbnails, or an image gallery, or an image with a 3D model attached that can be rendered in some tools for doing so (even online), etc.

  • Check if internft.org did something on this front
  • Check if there are existing solutions in Ethereum or other blockchains for this
  • Discuss options and ideas, especially considering we have the data field as well which might include info, so we need to accommodate both data from metadata, and data native to the NFT. Alternatively, look into removing support for NFT-native data in favor of IPFS or another decentralized storage solution.

RIP-002: Embedded NFT content

RIP Summary

There is currently a hard dependency on the metadata field to find out information about an NFT. This RIP proposes to add a native field to NFT entities that could hold the representative data verbatim and would make the metadata field optional. Additionally, several protocols are suggested as official types of data to be held, also upgrading the metadata field.

RIP Details

We propose adding a new data field to the Entity. The data field is to be composed of:

  • protocol (see Protocols below)
  • data
  • type (mime type)

We also propose adding the same data field to EntityMetadata.

If present in the Entity, that data takes precedence. Metadata is always secondary - on-chain information is prioritized as canonical at all times.

Protocols

Protocol Mime default Description
ipfs image/png Points to a directly interpretable resource, be it audio, video, code, or something else
http(s) image/html Points to a directly interpretable resource, be it audio, video, code, or something else (not recommended for use)
p5 application/javascript Processing.js code
js application/javascript Plain JS code
html text/html HTML code, no need for <html> and <body>, can support dependencies but it's up to the author to prevent the dependencies from disappearing
svg image/svg+xml SVG image data
bin n/a binary, directly interpretable

Examples

A binary video

data: {
  "protocol": "bin",
  "data": "AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAQC0ttZGF0AQIUGRQmM...",
  "type": "video/mp4"
}

JavaScript

data: {
  "protocol": "js",
  "data": "alert(\"Hello World\")",
  "type": "application/javascript"
}

The above, when interpreted, should immediately pop up a "Hello World" message.

Open questions

  • what about JS dependencies in js mode? Do we support defining deps somehow, or should this be up to the developer / artist entirely?

Prior work (optional)

Inspired by ArtBlocks' ability to have code-based NFTs.

Impact

This is a major change, so a major version bump is recommended.

Implementers:

  • SHOULD prevent auto-render and auto-play of non-media resources, and in some cases of media resources, to protect end users from cross site scripting, crash attacks (malicious NFTs), and other nefarious actors.
  • SHOULD expect the mime type to be there, but if missing, default to one common for the protocol, e.g. use application/javascript is mime type is missing but protocol is js.

RIP-0015 Royalties after migration RMRK2 -> RMRK3 = SUBSTRATE ACC-> EVM ACC

  • author(s): sage.rich
  • contact: discord
  • RIP type: addition

RIP Summary

RMRK2 royalties will link to some substrate (KSM) adress that doesn't match the network in which the fees will be paid after migration to RMRK3 (EVM address on MOVR/GLMR)

Examples

Royalties linked to account [substrate] will be hardcoded into the NFT, after migration the network will be on EVM with $MOVR/$GLMR. Thus the % for royalties can't be redirected to the substrate address.

Open Questions

Possible Solutions to consider:

  • coding a fitting EVM address into the royalties from the start for future compatibility (would need UI change in singular to provide second adress).
  • giving creators the option later to add some EVM address for their royalties for each NFT - problem, could be abused, e.g. if there were royalties splitted among two artists, half of the NFTs one, half with the other KSM addy, the creator could leech both parts into a new EVM addy under the artists control
  • having some mapping table, were KSM addys are linked to EVM addys by the owner of the KSM addy (would need UI and would have lost royalties for non signing artists)
  • prefered option: having some internal swapping mechanism via karura or some other DEX, royalties with unfitting (substrate) account are relinked to some RMRK owned multisig EVM with contracts that swap into KSM/substrate currency and send the swapped royalties to the NFT-internal substrate addy (problem would be tx fees & swap fees for very small royalties e.g. for sales with 0.005 MOVR as price)

Impact

Migration to RMRK3 might "kill" royalties for older collections if no solution comes up. That would mean migrating collections would be disadvantagous for artists. Without migration RMRK NFTs might be scattered around on RMRK1, RMRK2 and RMRK3 plattforms.

Support any CSS color value for NFT metadata

  "background_color": {
    "type": "string",
    "description": "Background color of the item. Must be a six-character hexadecimal without #."
  },

Kanaria is using HEX format with # prefix

The goal of this issue is to support any CSS Color Value (except current color)

With CSS, colors can be specified in different ways:

By color names
As RGB values
As hexadecimal values
As HSL values (CSS3)
As HWB values (CSS4)

RIP-009: "Issuer-owned" Markets

RIP Summary

An extension/modification of the Buy and Mint interactions to allow issuers to specify a proportion of the value of the operation that must be paid directly to the current(?) issuer and previous owners of an NFT on purchase.

RIP Details

Issuance-side

An OPTIONAL additional field to the minified JSON for the MINT interaction - for the creator reward, or cr

1.0.0 Json:

{
  "name": "Dot Leap Early Promoters",
  "max": 100,
  "issuer": "CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp",
  "symbol": "DLEP",
  "id": "0aff6865bed3a66b-DLEP",
  "metadata": "ipfs://ipfs/QmVgs8P4awhZpFXhkkgnCwBp4AdKRj3F9K58mCZ6fxvn3j"
}

and post-upgrade:

{
  "name": "Dot Leap Early Promoters",
  "max": 100,
  "issuer": "CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp",
  "symbol": "DLEP",
  "id": "0aff6865bed3a66b-DLEP",
  "metadata": "ipfs://ipfs/QmVgs8P4awhZpFXhkkgnCwBp4AdKRj3F9K58mCZ6fxvn3j", 
  "cr": [10]
}

post-upgrade with additional rewards for "curators":

{
  "name": "Dot Leap Early Promoters",
  "max": 100,
  "issuer": "CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp",
  "symbol": "DLEP",
  "id": "0aff6865bed3a66b-DLEP",
  "metadata": "ipfs://ipfs/QmVgs8P4awhZpFXhkkgnCwBp4AdKRj3F9K58mCZ6fxvn3j", 
  "cr": [3, 1, 1, 5]
}

A value's position in the array of cr represents a Percent value of any Buy operation that should be sent to a historical owner of an NFT, and the final element represents the percentage that should be sent to the current issuer.

Both examples above represent 10% of the sale price of an NFT being sent to accounts other than the seller, but the first example represents 10% going entirely to the issuer, and the second represents 5% going to the issuer, with 3%, 1%, and 1% going to 3rd, 2nd, and immediate subsequent owners of the NFT prior to the current seller.

A quick hint for implementors to use when calculating which accounts are represented by which element in the cr list is (pseudocode):

// every historical owner of an NFT is prepended to 
// "owners" upon COMPLETION of their purchase
// ie, owners[0] is current owner of the NFT 
// elementIndex = index within `cr` to lookup
ownerAge = (cr.len() - elementIndex) - 1
if ownerAge > 0
  historicalOwner = owners[ownerAge]
else
  historicalOwner = issuer

Purchase-side

Currently, as of the 1.0.0 spec,
To complete a purchase, we submit a utility.batchAll call comprised of two transactions:

utility.batchAll([
  system.remark(
    0x726d726b3a3a4255593a3a312e302e303a3a353130353030302d306166663638363562656433613636622d56414c48454c4c4f2d504f54494f4e5f4845414c2d30303030303030303030303030303031
  ),
  tx.balances.transfer(CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp, 10000000000),
]);

where CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp is the current owner of an NFT.

This upgrade would require an additional check - did the collection have a non-zero cr when minted - and if this check is true, the sale amount is split between the seller and the issuer - in practice, this means that an additional transfer should be added to the batch.

An example of the above purchase with cr of 10, and issuer H9eSvWe34vQDJAWckeTHWSqSChRat8bgKHG39GC1fjvEm7y:

utility.batchAll([
  system.remark(
    0x726d726b3a3a4255593a3a312e302e303a3a353130353030302d306166663638363562656433613636622d56414c48454c4c4f2d504f54494f4e5f4845414c2d30303030303030303030303030303031
  ),
  tx.balances.transfer(CpjsLDC1JFyrhm3ftC9Gs4QoyrkHKhZKtK7YqGTRFtTafgp, 9000000000),
 
 tx.balances.transfer(H9eSvWe34vQDJAWckeTHWSqSChRat8bgKHG39GC1fjvEm7y, 1000000000),
]);

From the perspective of the purchaser, every element in the cr array represents an additional balances.transfer call to add to their batch, with the address of the recipient being a historical owner of the NFT.

Note that the proposed standard is to take the amount out of the stated listing price, and not add a fee on top of it - this is to prevent a purchaser paying more than the stated price for a listing.

Examples

I am creator, I create a collection and state that sales of NFTs within the collection are only valid when 1% of the sale price is sent to me as well as the current owner.

When someone buys an NFT that I am an issuer of, that is using this mechanism, they add an additional extrinsic to the batch with my cut.

So if I create a highly sought-after artwork, I will have a constant source of income - or if an artwork I created eventually gets sold for a very significant amount, I benefit from the appreciation.

Open Questions

should this be something modifyable by issuer? how would they do so?

should this be something that always goes to the "real" creator of a collection, or should this respect changeissuer?

what degree of precision should cr allow? (example above is Percent, but it may also be Permill, Perbill, represented by a decimal/floating value, etc.)

Should non-purchase transfers be disallowed to prevent out-of-channel sales of an NFT?

Prior work (optional)

Zora.co

Impact

This would be a backwards-incompatible change, so implementers should not display listings (for purchase) that use this feature - ie, they have a cr field in the collection - unless they have implemented it themselves. This should be easy to determine and filter for, however.

Tools would have to be modified so that consolidator may keep track of cr.len - 1 historical owners of an NFT.

RMRK: standard re-check

The recent flame was a motivational point for me to re-check standard.

Collection:

  • name: According to standard this should match [A-Za-z0-9_] (\w in JS) however, 99% of users want also space.
  • max: 0 is for max, but we need to distinguish between 0 and null.
  • symbol: Says nothing about format. Urban legend says that it should be slugify(symbol, '_').toUpperCase()

NFT:

  • instance: fair description however, it's confusing for users (I would derive it from the name)

RIP-0010 Remove redundant "opensea" fields from metadata standard

RIP Summary

Originally RMRK metadata spec was closely following Opensea metadata spec. I believe that Opensea is using a lot of redundant fields and now that we already started re-implementing some parts inspired by ERC-1155 like properties format instead of Opensea's attributes, we can drop more fields from opensea's and stop trying to be compatible with it.

  • animation_url is a redundant field on metadata, especially with RMRK2 when multi resourced NFT is supported and animation/video can be a separate resource rather than an extra field on metadata. Metadata should be use mostly for text (name, description) and properties (prev. attributes) plus a fallback image. And more complex media should go into resources

  • background_color has no clear use case and with RMRK2 we have themes instead that can be utilised

  • youtube_url - should be removed as it's a single platform lock and too specific to youtube

RIP Details

Therefore the proposed metadata format is

{
  "external_url": {
    "type": "string",
    "description": "HTTP or IPFS URL for finding out more about this project. If IPFS, MUST be in the format of ipfs://ipfs/HASH"
  },
  "image": {
    "type": "string",
    "description": "HTTP or IPFS URL to project's main image, in the vein of og:image. If IPFS, MUST be in the format of ipfs://ipfs/HASH"
  },
  "image_data": {
    "type": "string?",
    "description": "[OPTIONAL] Use only if you don't have the image field (they are mutually exclusive and image takes precedence). Raw base64 or SVG data for the image. If SVG, MUST start with <svg, if base64, MUST start with base64:"
  },
  "description": {
    "type": "string",
    "description": "Description of the nft. Markdown is supported."
  },
  "name": {
    "type": "string",
    "description": "Name of the NFT instance."
  },
  "properties": {
    "type": "array",
    "description": "A Map of JSON objects, inspired by Enjin's: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema"
  }
}

Examples

Some examples of the changes in action.

Open Questions

Questions for the community, to still be discussed.

Prior work (optional)

Citations, acknowledgments for inspiration, projects this RIP is emulating, etc.

Impact

What this means for implementers, version numbers, and other considerations.

RIP-0011

  • author(s): Yuri
  • contact: author contact method / info
  • RIP type: upgrade

RIP Summary

Invalidate a LIST interaction on a NFT if previous LIST on the same NFT happened within 5 block

RIP Details

This only applies to Substrate system.remark spec of RMRK standard. This is to prevent users from re-listing NFT rapidly and to give any client some time to update

Examples

export const validateMinBlockBetweenEvents = (
  opType: OP_TYPES,
  nft: NFTConsolidated,
  remark: Remark
) => {
  const lastChange = nft.changes
    .filter((change) => change.opType === opType)
    .sort((change, prevChange) => prevChange.block - change.block)?.[0];

  if (!lastChange?.block) {
    return true;
  }

  if (remark.block - lastChange.block < 5) {
    throw new Error(
      `[${OP_TYPES.LIST}] There should be minimum of 5 blocks between last ${opType} interaction: ${remark.remark}`
    );
  }
};

Open Questions

Prior work (optional)

Citations, acknowledgments for inspiration, projects this RIP is emulating, etc.

Impact

This was done in rmrk-tools over a month ago but wasn't reflected in spec

I have done some diffing and no NFT were affected at a time of rmrk-tools change, but since then Adam was running his most dangerous NFT game with rapid relisting. I have notified Other RMRK UIs of a change immediately, but I don't think it was implemented there

RIP-007

RIP Summary

With the addition of the version into the RMRK itself, the version inside the collection's data becomes unnecessary and is just dead data weight. This RIP proposes the removal of the version from the collection's data.

RIP Details

Previously, the MINT interaction looked like this:

rmrk::MINT::htmlencoded(JSON_OF_COLLECTION)

Now, the interaction is:

rmrk::MINT::RMRK1.0.0::htmlencoded(JSON_OF_COLLECTION)

With that, JSON_OF_COLLECTION does not need the collection's version field, and as such the Collection entity also does not need it.

This applies to NFT minting as well.

Impact

As this is going into V1 onward, it should not cause any problems. Even if the version is still included in the data objects, it will just cost more but do no damage.

RIP-0014 Add RESMODIFY and RESREMOVE interactions

  • author(s): Heorhii
  • contact: @SupremaLex
  • RIP type: upgrade

RIP Summary

Add RESMODIFY and RESREMOVE interaction, which NFT's owner should accept.

RIP Details

I propose to add two new interactions to NFT's resource system.
The RESREMOVE interaction allows the issuer of a collection to remove a resource from an NFT in that collection. If the issuer is also the owner of this NFT, this interaction also counts as a ACCEPT automatically.

This is useful if some resource becomes deprecated and if you don't want to use the PRIORITY system to simulate resources mutability. Also, this is useful if we assume that BASE resource can change over time, i.e., new fixed parts or slots are added, and we don't want to store all previous versions of this BASE resource.

The RESMODIFY interaction allows the issuer of a collection to modify a resource of an NFT in that collection. If the issuer is also the owner of this NFT, this interaction also counts as a ACCEPT automatically.

This also helps to keep Storage clean, i.e., don't store old versions of BASE.

Examples

Let's assume that we have a base1:

  "symbol": "kanaria_superbird",
  "type": "svg",
  "parts": [
    {
        "id": "left_wing_front",
        "src": "ipfs://ipfs/hash",
        "metadata": "ipfs://ipfs/hash"
    },
    {
        "id": "left_wing_back",
        "src": "ipfs://ipfs/hash",
        "metadata": "ipfs://ipfs/hash2"
    }
  ]

and some NFT, which Resource's array looks like

"resources": [
  {
      "id": "V1StG",
      "base": "base1",
      "parts": ["left_wing_front", "left_wing_back"]
  }
]

Now, we want to add "right_wing_front" and "right_wing_back" (or remove some already existed, but deprecated parts). We can do it via RESADD interaction, but in case we want to keep consistency and keep resources logic relation, we may want to allow base1 to support these two new parts, i.e.

"symbol": "kanaria_superbird",
"type": "svg",
"parts": [
  {
      "id": "left_wing_front",
      "src": "ipfs://ipfs/hash",
      "metadata": "ipfs://ipfs/hash"
  },
  {
      "id": "left_wing_back",
      "src": "ipfs://ipfs/hash",
      "metadata": "ipfs://ipfs/hash2"
  },
  {
      "id": "right_wing_front",
      "src": "ipfs://ipfs/hash",
      "metadata": "ipfs://ipfs/hash"
  },
  {
      "id": "right_wing_back",
      "src": "ipfs://ipfs/hash",
      "metadata": "ipfs://ipfs/hash2"
  }
]

We can create base1_version2 with the data mentioned above and RESADD it. Then we will achieve:

"resources": [
  {
      "id": "V1StG",
      "base": "base1",
      "parts": ["left_wing_front", "left_wing_back"]
  },
  {
      "id": "V1FsU",
      "base": "base1_version2",
      "parts": ["left_wing_front", "left_wing_back", "right_wing_front", "right_wing_back"]
  }
]

or we can have (if we have RESREMOVE & RESMODIFY):

"resources": [
  {
      "id": "V1StG",
      "base": "base1",
      "parts": ["left_wing_front", "left_wing_back", "right_wing_front", "right_wing_back"]
  }
]

or

"resources": [
  {
      "id": "V1FsU", // - new id, because of new resource
      "base": "base1", // but the name is the same
      "parts": ["left_wing_front", "left_wing_back", "right_wing_front", "right_wing_back"]
  }
]

Such an approach will add more flexibility to RMRK NFT's resource system. Both remove and modify requests should be accepted by NFT's owner, so decentralization is kept.

Open Questions

Does the community interested in this?

Impact

I can't comment on Solidity implementation, but in the case of Substrate, we need to modify rmrk-traits(RESREMOVE, RESADD signatures) rmrk-core pallet (RESREMOVE, RESADD implementations, Storage to track requested remove/change).

RIP-001: Block-ID pair

RIP Summary

Due to the ability to easily mint an NFT with an ID that's already been used, this might confuse wallets that rely only on IDs. Therefore, the canonical way to address NFTs should actually be blocknumber-ID. This can be a computed propery, i.e., you do not need to register that ID in the NFT, instead, you refer to an NFT of ID X by a combination of blocknumber and ID X.

RIP Details

n/a

Prior work (optional)

n/a

RIP-0013 accept change issuer

RIP Summary

The new owner of the collection should fire an ACCEPT command after it was passed to him through CHANGEISSUER

RIP Details

In order to prevent phishing attempts due to the fact that CHANGEISSUER only passes collection to the new owner and not NFTs, a new owner should ACCEPT incoming collection for issuer change to apply.

Original issuer retains all rights until the new issuer accepts it. The new issuer can only ACCEPT the incoming collection and nothing else

Examples

In the extrinsic version of RMRK standard, this can look like

RMRK::ACCEPTCOLLECTION::1.0.0::${collection_id}

Open Questions

Need to check a dump if someone did CHANGEISSUER multiple times on the same collection, as it should have failed because it wasn't accepted after the first time.

Prior work (optional)

?

Impact

In RMRK1 we need to make sure this doesn't affect any of existing collections. But since there's nothing that an issuer can do with his collection except for CHANGEISSUER again this shouldn't be a problem.

So the only thing that we need to check if someone did CHANGEISSUER multiple times on the same collection, as it should have failed because it wasn't accepted after the first time.

We also need to sync with Kodadot (@vikiival, @yangwao) and any indexer services like SubQuery and SubSquid


Thanks to @mmvds for hilighting this case

RIP-008: Mint to recipient

RIP Summary

Add ability to mint an NFT directly into someone else's account without having to MINTNFT + SEND. Without this, transferable === false is pointless because you cannot give non-transferable badges to someone else.

Examples

The proposed approach is to add a new field to the end of the MINTNFT interaction which would signify the recipient.

Instead of:

0x{bytes(rmrk::MINTNFT::{version}::{html_encoded_json})}

We would have

0x{bytes(rmrk::MINTNFT::{version}::{html_encoded_json}::{recipient})}

Concretely, if we have the MINTNFT operation of:

rmrk::MINTNFT::1.0.0::%7B%22collection%22%3A%220aff6865bed3a66b-DLEP%22%2C%22instance%22%3A%22DL15%22%2C%22name%22%3A%22Dot+Leap+15+Promo+NFT%22%2C%22transferable%22%3A1%2C%22sn%22%3A%220000000000000001%22%2C%22metadata%22%3A%22ipfs%3A%2F%2Fipfs%2FQmavoTVbVHnGEUztnBT2p3rif3qBPeCfyyUE5v4Z7oFvs4%22%7D

With a recipient of HviHUSkM5SknXzYuPCSfst3CXK4Yg6SWeroP6TdTZBZJbVT it would become:

rmrk::MINTNFT::1.0.0::%7B%22collection%22%3A%220aff6865bed3a66b-DLEP%22%2C%22instance%22%3A%22DL15%22%2C%22name%22%3A%22Dot+Leap+15+Promo+NFT%22%2C%22transferable%22%3A1%2C%22sn%22%3A%220000000000000001%22%2C%22metadata%22%3A%22ipfs%3A%2F%2Fipfs%2FQmavoTVbVHnGEUztnBT2p3rif3qBPeCfyyUE5v4Z7oFvs4%22%7D::HviHUSkM5SknXzYuPCSfst3CXK4Yg6SWeroP6TdTZBZJbVT

Impact

  • the UIs would have to recognize this field to auto-assign an NFT to the recipient
  • the tools would need updated:
    • the Consolidator needs to become aware of this and change the NFT's owner
    • the NFT's fromRemark functionality needs to be updated
    • the NFT's toRemark functionality needs to be updated

RIP-006: Add EMOTE interaction

RIP Summary

This proposal brings EMOTE interaction to the RMRK system. Emote interaction shows the caller's appreciation towards a particular Collection or NFT.

RIP Details

We propose to add EMOTE interaction as a new form.
The goal of this interaction is to give the ability to express positive feedback to NFT or Collection. Collection authors will get instant feedback on their art and it should motivate them to create more.

The possible format of a EMOTE interaction is 0x{bytes(RMRK::EMOTE::{version}::{id}::{emotion})}.

  • version is the version of the standard used (e.g. RMRK1.0.0)
  • id represents the id of NFT or Collection.
  • emotion Unicode of a selected emoji (e.g Unicode for party popper πŸŽ‰ is 1F389

Currently, we would like to support the following set of emojis:
πŸ€” , πŸ’–, πŸ‘ , 😘, πŸ’‘, πŸ‘€ , πŸŽ‰, 😊 , πŸ¦„ , πŸ™Œ , 🀯 , πŸ™

Examples

Suppose we have the following NFT:

{
  "collection": "0aff6865bed3a66b-VALHELLO",
  "name": "POTION_HEAL",
  "transferable": 1,
  "sn": "0000000000000001",
  "metadata": "ipfs://ipfs/QmavoTVbVHnGEUztnBT2p3rif3qBPeCfyyUE5v4Z7oFvs4"
}

To show appreciation towards NFT or Collection we call system.remark with the following parameter:

RMRK::EMOTE::RMRK1.0.0::0aff6865bed3a66b-VALHELLO-POTION_HEAL-0000000000000001::1F389

Open Questions

  1. Should the following standard support a bigger set or all available Unicode emojis?
    We think that keeping a small set makes parsing simpler and we would like to ensure that emojis are visible on all major operating systems.

Impact

Calling EMOTE with the same parameters acts as an undo operation.

Citing @Swader:

New idea I had about EMOTE: even number = not emoted, odd number means = emoted. 
So to remove a moon emote, you just send another moon.
Then to moon it again, you again send a moon.
This keeps things consistent
and we don't have to deal with keeping track of remove and add emotes 

RIP-0017 Remove `theme` from on-chain, move it to metadata spec

  • author(s): Yuri Petusko
  • contact: @Yuripetusko
  • RIP type: upgrade

RIP Summary

We shouldn't be saving theme object on-chain and instead adding it as a property to add to metadata and saved on IPFS

RIP Details

There's no point, and often not possible (like on evm/substrate) to save theme object arbitrary shape on-chain, we should instead add it as optional property to save alongside other metadata properties and write a guide for consumers/clients on how to parse and use with different base types, starting with SVG base (catalog).

Examples

const metadataFields: Metadata = {
  mediaUri: 'ipfs://ipfs/xxx',
  externalUri: 'https://singular.app',
  name: 'Rare #333,
  description: 'Very rare bird',
  theme: {theme_color_1: '#dd6195', theme_color_2: '#fdb453', theme_color_3: '#370842', theme_color_4: '#8f2386'}
};

Open Questions

Questions for the community, to still be discussed.

Prior work (optional)

Citations, acknowledgments for inspiration, projects this RIP is emulating, etc.

Impact

We don't have many existing NFTs which use theme so this shouldn't impact many

RIP-0012

RIP Summary

Add a seal method to a collection to immediately set max field of a collection to current nft length

RIP Details

Collection issuer should be able to call a seal command to make unlimited collection to a limited collection, or change max to a current nft length in said collection

Examples

Collection.seal();

Open Questions

Questions for the community, to still be discussed.

Prior work (optional)

Citations, acknowledgments for inspiration, projects this RIP is emulating, etc.

Impact

What this means for implementers, version numbers, and other considerations.

BASE requires issuer

Seems that a BASE interaction requires issuer be explicitly stated. See the following dump:

  {
    "op_type": "BASE",
    "block": 12324513,
    "caller": "JFBzbixEKomf36X6GDDkNmxXZE3dk5imbKsS6CR3fez1G8c",
    "object_id": "rmrk::BASE::2.0.0::{\"symbol\"%3A \"test_stickie_base\"%2C\"type\"%3A \"png\"%2C\"parts\"%3A [{\"id\"%3A \"body\"%2C\"src\"%3A \"ipfs%3A%2F%2Fipfs%2FQmZZegFEeeTtzWZmNX3HorPrA4cgvsvVq2RedWdaLqFYWu\"%2C\"type\"%3A \"fixed\"%2C\"z\"%3A 1}%2C{\"id\"%3A \"right\"%2C\"type\"%3A \"slot\"%2C\"equippable\"%3A [\"12345abcde-TEST_RMRK_2_COLLECTION\"]%2C\"z\"%3A 2}%2C{\"id\"%3A \"left\"%2C\"type\"%3A \"slot\"%2C\"equippable\"%3A [\"12345abcde-TEST_RMRK_2_COLLECTION\"]%2C\"z\"%3A 2}]}",
    "message": "[BASE] Dead before instantiation: At path: issuer -- Expected a string, but received: undefined"
  },

This might be an issue with rmrk-tools, but putting it here because I found it here.

RIP-0016 Add optional metadata field to BASE

RIP Summary

Add metadata field to BASE body

RIP Details

Allow to add a metadata field to BASE body to be able to give name and thumbnail to your BASE, this is useful when visualising all the created BASEs to user on the client

Examples

{
    "symbol": "kanaria_superbird",
    "metadata": "ipfs://ipfs/XXX",
    "type": "svg",
    "parts": [
      {
          "id": "bg",
          "src": "ipfs://ipfs/hash",
          "thumb": "ipfs://ipfs/hash",
          "type": "slot",
          "equippable": ["collection_1", "collection_2"],
          "z": 3
      },
      {
          "id": "gem_1",
          "src": "ipfs://ipfs/hash",
          "type": "fixed",
          "z": 4
      },
      {
          "id": "wing_1_back",
          "src": "ipfs://ipfs/hash",
          "metadata": "ipfs://ipfs/hash"
      },
      {
          "id": "wing_1_front",
          "metadata": "ipfs://ipfs/hash2"
      }
    ]
}

Open Questions

N/A

RIP-003: Composite NFTs

RIP Summary

This RIP proposes a standard upgrade to allow for composite (layered) NFTs and custom collections.

RIP Details

This proposal aims to introduce tie-ins between NFTs that make them influence each other, and aims to introduce a new entity - custom collections - which allow users to create new collections of interdependent art the properties of which affect the greater whole.

NFT Dependencies

A user can make an NFT have other NFTs as dependencies, and can define certain properties of the NFT as affected by properties of its dependencies.

TBD

Custom Collections

A user is able to create a custom view collection which is composed of other NFTs. This collection is an NFT itself and can be traded.

TBD

Mutable Properties

To make the above possible, mutable properties are introduced - simple strings and switches an NFT's owner can flip and change. These changes propagate up the chain of dependents.

TBD

Examples

TBD

Open Questions

TBD

Prior work (optional)

  • Async Art has done some experiments in the layered NFT space where certain NFTs are rendered as part of a collection and the changed properties of one NFT are reflected in the collection being viewed.

Impact

This is a major change due to new entities being introduced, so a major version bump is recommended.

Add spec check

Add tools that verify constructed remark matches the standard for its interaction or entity. Example: check if collection's metadata is a URL, if the symbol matches the ID part it needs to match, if the ID of an ID is parseable into name, ID, block, etc.

RIP-005: Change batch to batchAll across all documents

RIP Summary

Recommend batchAll instead of batch.

RIP Details

The 0.1 standard recommends using batch in several places. Now that batchAll in available, batch should be deemed insecure and avoided, as it's much easier to get partial failures with it which might break various tools and consolidators.

Impact

Starting with RMRK1.0.0 implementers MUST discard any and all remarks in batch and MUST ONLY process remarks done without batching or with batchAll.

RIP-004: Migrate Collection

RIP Summary

The MIGRATE interaction allows for porting a collection from a previous standard to the current standard in which the MIGRATE interaction is defined.

RIP Details

The MIGRATE interaction can only be called on Collections, and immediately applies to all child NFTs. The MIGRATE interaction can only be called by the current issuer of the collection.

Some fields might get dropped during a migration (i.e. a change from computed to static property or vice versa) while others may get added (e.g. RIP 002 or RIP 003).

Impact and notes

Tools should allow users to migrate their collections. Tools should not allow interactions across RMRK standard versions and should instead force a user to upgrade to the new standard version first.

Interactions that have been emitted using a previous standard (e.g. a LIST issued under 0.1 and the collection containing the listed item moving to 0.2) are still fine and to be interpreted by the tools according to the originally specified standard version. Given that interactions are short lived, no migration is necessary. A notable exception can be the LIST interaction which can be CANCELED and re-issued using the new standard if needed (in case of bugs found in the previous standard's implementation or other concerns).

RIP-016 "Auto-Accept" attribute

  • author(s): Gabriel
  • contact: Telegram
  • RIP type: addition

RIP Summary

We are looking to add a soulbound collection the Governance Participation Rewards. The idea is to have an NFT with many attributes where these attributes fully represent a wallet's on-chain activity. Whenever a wallet participates in a new vote for example, a new attribute should be added to that NFT by pushing a new resource.

RIP Details

In order to have a nice UX, such NFTs should allow "auto-accepting" of resources. I propose to add a "auto-accept" attribute to the NFTs (which defaults to false) to allow for the above use-case. When "auto-accept" is set to true, new resources pushed by the NFT creator will automatically be accepted without requiring manual accepting from the User. This functionality should NOT encompass resource replacements. Resource replacements should still have to be manually accepted by users.

Examples

Such a feature might also be interesting for NFT games for example. Perhaps a players avatar should "automatically" get updated as they complete a mission and level-up.

Open Questions

Can you think of any negative side-effects of such a feature?
Should the auto-accept attribute be on the collection level rather than the nft level?

Impact

By defaulting the new attribute to "false", the impact should be minimal for implementers. It would of course require an update of the rmrk-tools especially in the logic of minting an NFT and accepting new resources. An update to marketplaces "warning" users of automatic acceptance would also be required.

RIP-XXX (please change XXX to number)

  • author(s): author name(s)
  • contact: author contact method / info
  • RIP type: [upgrade | addition]

RIP Summary

A one-paragraph summary of your RIP.

RIP Details

Explain your RIP here in depth.

Prior work (optional)

Citations, acknowledgments for inspiration, projects this RIP is emulating, etc.

RIP-0012

RIP Summary

ability to Destroy a collection

RIP Details

DESTROY an existing Collection (one that has not been destroyed yet), only if you are it's issuer and as long as it doesn't contain any unburned NFTs.

Examples

RMRK::DESTROY::2.0.0::0a24c7876a892acb79-PUNKS

Open Questions

Questions for the community, to still be discussed.

Prior work (optional)

Citations, acknowledgments for inspiration, projects this RIP is emulating, etc.

Impact

What this means for implementers, version numbers, and other considerations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.