Create nftokenpage.md

This commit is contained in:
Dennis Dawson
2022-01-06 11:35:53 -08:00
committed by GitHub
parent 4d4db9e25b
commit 8a216c93d3

View File

@@ -0,0 +1,241 @@
---
html: nftokenpage.html
parent: ledger-object-types.html
blurb: Ledger structure for recording NFTokens.
filters:
- include_code
labels:
- Non-fungible Tokens, NFTs
status: not_enabled
---
# The `NFTokenPage` Object
{% include '_snippets/nfts-disclaimer.md' %}
The `NFTokenPage` object represents a collection of `NFToken` objects owned by the same account. An account can have multiple `NFTokenPage` ledger objects, which form a doubly-linked list (DLL).
## Example {{currentpage.name}} JSON
```json
{
"LedgerEntryType": "NFTokenPage",
"PreviousTokenPage":
"598EDFD7CF73460FB8C695d6a9397E907378C8A841F7204C793DCBEF5406",
"PreviousTokenNext":
"598EDFD7CF73460FB8C695d6a9397E9073781BA3B78198904F659AAA252A",
"PreviousTxnID":
"95C8761B22894E328646F7A70035E9DFBECC90EDD83E43B7B973F626D21A0822",
"PreviousTxnLgrSeq":
42891441,
"Tokens":
{
{
"TokenID":
"000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65",
"URI":
"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi"
},
/* potentially more objects */
}
}
```
In the interest of minimizing the size of a page and optimizing storage, the `Owner` field is not present, since it is encoded as part of the object's ledger identifier.
## {{currentpage.name}} Fields
An `NFTokenPage` object can have the following required and optional fields:
<table>
<tr>
<td><strong>Field Name</strong>
</td>
<td><strong>Required?</strong>
</td>
<td><strong>JSON Type</strong>
</td>
<td><strong>Internal Type</strong>
</td>
<td><strong>Description</strong>
</td>
</tr>
<tr>
<td><code>LedgerEntryType</code>
</td>
<td>Yes
</td>
<td>string
</td>
<td>UINT16
</td>
<td>Identifies the type of ledger object. The reserved ledger entry type is <code>0x0050</code>.
</td>
</tr>
<tr>
<td><code>PreviousPageMin</code>
</td>
<td>No
</td>
<td>string
</td>
<td>UINT256
</td>
<td>The locator of the previous page, if any. Details about this field and how it should be used are outlined below, after the construction of the <code>NFTokenPageID</code> is explained.
</td>
</tr>
<tr>
<td><code>NextPageMin</code>
</td>
<td>No
</td>
<td><code>string</code>
</td>
<td><code>UINT256</code>
</td>
<td>The locator of the next page, if any. Details about this field and how it should be used are outlined below, after the construction of the <code>NFTokenPageID</code> is explained.
</td>
</tr>
<tr>
<td><code>PreviousTxnID</code>
</td>
<td>No
</td>
<td><code>string</code>
</td>
<td><code>HASH256</code>
</td>
<td>Identifies the transaction ID of the transaction that most recently modified this <code>NFTokenPage</code> object.
</td>
</tr>
<tr>
<td><code>PreviousTxnLgrSeq</code>
</td>
<td>No
</td>
<td><code>number</code>
</td>
<td><code>UINT32</code>
</td>
<td>The sequence of the ledger that contains the transaction that most recently modified this <code>NFTokenPage</code> object.
</td>
</tr>
<tr>
<td><code>NonFungibleTokens</code>
</td>
<td>Yes
</td>
<td><code>object</code>
</td>
<td><code>TOKEN</code>
</td>
<td>The collection of <code>NFToken</code> objects contained in this <code>NFTokenPage</code> object. This specification places an upper bound of 32 <code>NFToken</code> objects per page. Objects should be stored in sorted order, from low to high with the <code>TokenID</code> used as the sorting parameter.
</td>
</tr>
</table>
### TokenPage ID Format
`NFTokenPage` identifiers are constructed so as to specifically allow for the adoption of a more efficient paging structure, ideally suited for `NFTokens`.
The identifier of an `NFTokenPage` is derived by concatenating the 160-bit `AccountID` of the owner of the page, followed by a 96 bit value that indicates whether a particular `TokenID` can be contained in this page.
More specifically, and assuming that the function `low96(x)` returns the low 96 bits of a 256-bit value, an NFT with `TokenID` `A` can be included in a page with `NFTokenPageID` `B` if and only if `low96(A) >= low96(B)`.
For example, applying the `low96` function to the NFT described before, which had an ID of `000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65` the function `low96` would return `42540EE208C3098E00000D65`.
This curious construct exploits the structure of the SHAMap to allow for efficient lookups of individual `NFToken` objects without requiring iteration of the doubly-linked list of `NFTokenPages`.
### Searching for an `NFToken` object
To search for a specific `NFToken`, compute the `NFTokenPageID` using the account of the owner and the `TokenID` of the token, as described above. Search for a ledger entry where the identifier is less than or equal to that value. If that entry does not exist or is not an `NFTokenPage`, the `NFToken` is not held by the given account.
### Adding an `NFToken` object
You add an `NFToken` object by finding the `NFTokenPage` it should be in (using the same technique as searching for an `NFToken` object) and adding it to that page. If the page overflows after you add the `NFToken`, find the `next` and `previous` pages (if any) and balance those three pages, inserting a new page as needed.
### Removing an `NFToken` object
An `NFToken` can be removed by using the same approach. If the number of `NFTokens` in the page goes below a certain threshold, the server attempts to consolidate the page with a previous or subsequent page to recover the reserve.
### Reserve for `NFTokenPage` object
Each `NFTokenPage` costs an incremental reserve to the owner account. This specification allows up to 32 `NFToken` entries per page, which means that for accounts that hold multiple NFTs the _effective_ reserve cost per NFT can be as low as _R_/32 where _R_ is the incremental reserve.
### The reserve in practice
The value of the incremental reserve is, as of this writing, 2 XRP. The table below shows what the _effective_ reserve per token is, if a given page contains 1, 8, 16, 32 and 64 NFTs.
<table>
<tr>
<td><strong>Incremental Reserve</strong>
</td>
<td><strong>1 NFT</strong>
</td>
<td><strong>8 NFTs</strong>
</td>
<td><strong>16 NFTs</strong>
</td>
<td><strong>32 NFTs</strong>
</td>
<td><strong>64 NFTs</strong>
</td>
</tr>
<tr>
<td>5 XRP
</td>
<td>5 XRP
</td>
<td>0.625 XRP
</td>
<td>0.3125 XRP
</td>
<td>0.15625 XRP
</td>
<td>0.07812 XRP
</td>
</tr>
<tr>
<td>2 XRP
</td>
<td>2 XRP
</td>
<td>0.25 XRP
</td>
<td>0.125 XRP
</td>
<td>0.0625 XRP
</td>
<td>0.03125 XRP
</td>
</tr>
<tr>
<td>1 XRP
</td>
<td>1 XRP
</td>
<td>0.125 XRP
</td>
<td>0.0625 XRP
</td>
<td>0.03125 XRP
</td>
<td>0.01562 XRP
</td>
</tr>
</table>
<!--{# common link defs #}-->
{% include '_snippets/rippled-api-links.md' %}
{% include '_snippets/tx-type-links.md' %}
{% include '_snippets/rippled_versions.md' %}