Skip to content

Commit dba89c1

Browse files
mvadariTapanito
andcommitted
Add XLS-16d: 0016 XLS-16d: NFT Metadata (XRPLF#318)
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
1 parent 32b88cd commit dba89c1

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed

XLS-0016-nft-metadata/README.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<pre>
2+
xls: 16
3+
title: NFT Metadata
4+
author: Hubert Getrouw (@HubertG97)
5+
created: 2021-03-17
6+
status: Stagnant
7+
category: Community
8+
</pre>
9+
10+
In addition to @WietseWind 's [XLS-14d](https://github.com/XRPLF/XRPL-Standards/discussions/30) and @RichardAH 's proposal [XLS-15d](https://github.com/XRPLF/XRPL-Standards/discussions/34) here is a proposal to create a standard for the creation of metadata for the tokens created with a CTI in the currency code.
11+
12+
When issuing an indivisible token on the XRPL the only data given is the currency code. For optimal usage, there has to be more metadata for an NFT. For example a description and a URI to an IPFS file.
13+
Using the Concise Transaction Identifier, a prior transaction can be used to mark the metadata contained in the memo's field for the use of the NFT.
14+
15+
The [Memos Field](https://xrpl.org/transaction-common-fields.html#memos-field) in an XRPL transaction is presented as an array of objects which contains one memo field per object. This field consists of the following fields:
16+
17+
- MemoData
18+
- MemoFormat
19+
- MemoType
20+
21+
The MemoData field can be used for the metadata itself and the MemoFormat indicates the nature of the given data inside the MemoData field (MIME type). To create a certain hierarchy for covering failure of the URI specified, the MemoType field contains the numbering of the data named as shown below followed by the MIME type:
22+
23+
- NFT/0 - _Description_ - `text/plain`
24+
- NFT/1 - _Author_ - `text/plain`
25+
- NFT/2 - _Primary URI_ - `text/uri`
26+
- NFT/3 - _Back-up URI_ - `text/uri`
27+
- NFT/4 - _Reduced image Data URI as last back-up_ - `text/uri`
28+
29+
The usage of a back-up URI and Data URI can be seen as optional and can be replaced with other kinds of data that have the preference of the issuer of the NFT for example contact information.
30+
The limit of storage is 1kb of data in the memo's field in total. Multiple memos can be used to give as much information as fits to the 1kb of data.
31+
32+
If there is only one memo on the CTI referenced transaction and the memo data contains a URI of any sort then this is deemed to be the NFT content. The multiple memo's structure will be the advanced method to issue NFTs. The standard will also be compatible with previously created NFTs referred to as the simple method.
33+
34+
---
35+
36+
**Issuing**
37+
38+
For the metadata, there has to be created a transaction from the same address as the issuer of the NFT to for example a hot wallet. This transaction of 1 drop contains the description and URIs needed for the NFT.
39+
40+
The currency code for an NFT consists of 3 parts:
41+
42+
- Prefix 02 for HEX currency code
43+
- [CTI](https://github.com/XRPLF/XRPL-Standards/discussions/34) (Concise Transaction Identifier)
44+
- Short name converted to HEX for the NFT to a maximum of 12 characters or less (filled up with 0's if it's less)
45+
46+
After this, a Trust line can be set up using the above currency code and the NFTs being transferred from the issuing address to the hot wallet.
47+
48+
---
49+
50+
### Advanced method
51+
52+
_For example_
53+
54+
**Issuer:** `rBzoA1EXxE2FeGV4Z57pMGRuzd3dfKxVUt`
55+
**Hot wallet:** `rp9d3gds8bY7hkP8FmNqJZ1meMtYLtyPoz`
56+
57+
The JSON for the metadata transaction would look like this:
58+
59+
```
60+
{
61+
"Account": "rBzoA1EXxE2FeGV4Z57pMGRuzd3dfKxVUt",
62+
"TransactionType": "Payment",
63+
"Amount": "1",
64+
"Destination": "rp9d3gds8bY7hkP8FmNqJZ1meMtYLtyPoz",
65+
"Fee": "100000",
66+
"Memos": [{
67+
"Memo": {
68+
"MemoData": "546861742773206F6E6520736D616C6C20696D616765206F66206D6F6F6E2C206F6E65206769616E74206C65617020666F72204E4654206F6E20746865205852504C",
69+
"MemoFormat": "746578742F706C61696E",
70+
"MemoType": "6E66742F30"
71+
}
72+
},
73+
{
74+
"Memo": {
75+
"MemoData": "48756265727420476574726F7577",
76+
"MemoFormat": "746578742F706C61696E",
77+
"MemoType": "6E66742F31"
78+
}
79+
},
80+
{
81+
"Memo": {
82+
"MemoData": "697066733A2F2F62616679626569686561786B696A3276656D6B7337726B716E6F67367933367579793337626B33346D697533776F72636A756F6833747532773279",
83+
"MemoFormat": "746578742F757269",
84+
"MemoType": "6E66742F32"
85+
}
86+
},
87+
88+
{
89+
"Memo": {
90+
"MemoData": "68747470733A2F2F676574726F75772E636F6D2F696D672F707572706C656D6F6F6E2E706E67",
91+
"MemoFormat": "746578742F757269",
92+
"MemoType": "6E66742F33"
93+
}
94+
},
95+
{
96+
"Memo": {
97+
"MemoData": "646174613A696D6167652F6769663B6261736536342C52306C474F446C684641415541505141414141414142415145434167494441774D4542415146425155474267594842776348392F66342B506A352B666E362B7672372B2F76382F507A392F66332B2F76377741414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414143483542414541414241414C4141414141415541425141414157524943534F5A476D65614B7175624F74437A664D7551564D456937674D41494D554D684942554F4D784941454141544A736942674F4A674267654267456A476E413063673945524446464342364E4D6248305945684543454579784844414354316571383352486C69654D73474147414641414949436A495051776F4F66675A4A41544A5A5932414C4255634B535A516A684552424A41384355774F6750414B6649326445547156554A6A774166364345435352694F436F4D42416F6A6A61675149514137",
98+
"MemoFormat": "746578742F757269",
99+
"MemoType": "6E66742F34"
100+
}
101+
}]
102+
103+
104+
}
105+
```
106+
107+
Converted to human-readable output's [this](https://xrpcharts.ripple.com/#/transactions/24ADC5D0EF72DDA45A7464A7F74B762801FA12C26F6BFEEFC61CF72140623F27) transaction
108+
109+
Using this transaction's txn hash, txn_index, ledger_hash, and ledger_index creates a CTI of `23080995397183855`
110+
Converted to HEX it will be `52000B03B6296F`
111+
112+
The name of the NFT will be '_Purple moon_'.
113+
After conversing this to HEX the complete currency code looks like this `0252000B03B6296F507572706C65206D6F6F6E00`
114+
115+
**02** - _XRPL NFT identifier_
116+
**52000B03B6296F** - _CTI_
117+
**507572706C65206D6F6F6E00** - _NFT name_
118+
119+
When Issuing a token the same address has to be used as the sender of the aforementioned transaction.
120+
As explained in this [blogpost](https://coil.com/p/Huub/Introduction-to-NFT-on-the-XRP-Ledger/4ee41zWW-) a Trust line has to be created between the Issuer and the hot wallet.
121+
122+
Make sure the issuer address has an `AccountSet` of `SetFlag` to `8`
123+
124+
```
125+
{
126+
"TransactionType": "TrustSet",
127+
"Account": "rp9d3gds8bY7hkP8FmNqJZ1meMtYLtyPoz",
128+
"Fee": "12",
129+
"Flags" : 131072,
130+
"LimitAmount": {
131+
"currency": "0252000B03B6296F507572706C65206D6F6F6E00",
132+
"issuer": "rBzoA1EXxE2FeGV4Z57pMGRuzd3dfKxVUt",
133+
"value": "1000000000000000e-95"
134+
}
135+
}
136+
```
137+
138+
In the currency field the HEX converted currency code is used.
139+
The value is set to `1000000000000000e-95` which will result in 10 NFTs.
140+
More explanation about this can be found in @WietseWind's proposal [XLS-14d](https://github.com/XRPLF/XRPL-Standards/discussions/30)
141+
142+
Last step is to send the tokens from the issuer to the hot wallet.
143+
144+
```
145+
{
146+
"TransactionType": "Payment",
147+
"Account": "rBzoA1EXxE2FeGV4Z57pMGRuzd3dfKxVUt",
148+
"Fee": "12",
149+
"Destination" : "rp9d3gds8bY7hkP8FmNqJZ1meMtYLtyPoz",
150+
"Amount": {
151+
"currency": "0252000B03B6296F507572706C65206D6F6F6E00",
152+
"issuer": "rBzoA1EXxE2FeGV4Z57pMGRuzd3dfKxVUt",
153+
"value": "1000000000000000e-95"
154+
}
155+
}
156+
```
157+
158+
Now there are 10 Purple moon NFTs on address `rp9d3gds8bY7hkP8FmNqJZ1meMtYLtyPoz`
159+
160+
### Simple Method
161+
162+
The JSON for the metadata transaction would look like this:
163+
164+
```
165+
{
166+
"Account": "rBzoA1EXxE2FeGV4Z57pMGRuzd3dfKxVUt",
167+
"TransactionType": "Payment",
168+
"Amount": "1",
169+
"Destination": "rp9d3gds8bY7hkP8FmNqJZ1meMtYLtyPoz",
170+
"Fee": "100000",
171+
"Memos": [{
172+
"Memo": {
173+
"MemoData": "697066733A2F2F62616679626569666C6A667870786F7A6E6A703273357266697270666A756E7876706B71737863727133766C626F6C346536717A376F7972693571",
174+
"MemoFormat": "746578742F757269",
175+
"MemoType": "7872706C2F6E6674"
176+
}
177+
}]
178+
}
179+
```
180+
181+
Converted to human-readable output's [this](https://xrpcharts.ripple.com/#/transactions/7DFCD417FCEE35F7BB3ABECD05C27BA71F1E845BFD29C19AF3CF5E55B44EA55C) transaction
182+
183+
After that, a trust set and sending the tokens is the same as the advanced method

0 commit comments

Comments
 (0)