mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-20 11:45:50 +00:00
NFT doc format cleanup
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
[汎用エラータイプ]: error-formatting.html#汎用エラー
|
||||
[XRP, in drops]: basic-data-types.html#specifying-currency-amounts
|
||||
[XRP、drop単位]: basic-data-types.html#通貨額の指定
|
||||
[NFToken]: nftoken.html
|
||||
|
||||
<!-- API object types -->
|
||||
{% set ledger_entries = [
|
||||
@@ -69,7 +70,6 @@
|
||||
"FeeSettings",
|
||||
"LedgerHashes",
|
||||
"NegativeUNL",
|
||||
"NFToken",
|
||||
"NFTokenOffer",
|
||||
"NFTokenPage",
|
||||
"Offer",
|
||||
|
||||
@@ -12,7 +12,7 @@ status: not_enabled
|
||||
# NFT Conceptual Overview
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
The XRP Ledger offers support for tokens, also known as _IOUs _or _issued assets_. Such assets are, primarily, fungible.
|
||||
The XRP Ledger offers support for tokens, also known as _IOUs_ or [_issued currencies_](issued-currencies.html). Such assets are, primarily, fungible.
|
||||
|
||||
> Fun·gi·ble /ˈfənjəbəl/ (adj)
|
||||
>
|
||||
@@ -29,7 +29,6 @@ But since you are standing around in 1919, you might be offered 24-cent airmail
|
||||
|
||||

|
||||
|
||||
|
||||
Those stamps cannot be replaced by just another other 24-cent stamp. They have become _non-fungible_.
|
||||
|
||||
The XRPL Labs team has created a framework that supports non-fungible tokens (NFTs, or “nifties” in the vernacular). Non-fungible tokens serve to encode ownership of unique physical, non-physical, or purely digital goods, such as works of art or in-game items.
|
||||
@@ -39,15 +38,15 @@ The XRPL Labs team has created a framework that supports non-fungible tokens (NF
|
||||
|
||||
Extensions to the XRP Ledger support two new objects and a new ledger structure.
|
||||
|
||||
The <code>[NFToken](references/protocol-reference/ledger-data/ledger-object-types/nftoken.html)</code> is a native NFT type. It has operations to enumerate, purchase, sell, and hold such tokens. An <code>NFToken</code> is a unique, indivisible unit that is not used for payments.
|
||||
The [NFToken][] is a native NFT type. It has operations to enumerate, purchase, sell, and hold such tokens. An `NFToken` is a unique, indivisible unit that is not used for payments.
|
||||
|
||||
<code>[NFTokenPage](references/protocol-reference/ledger-data/ledger-object-types/nftokenpage.html)</code> is a ledger structure that contains a set of <code>NFToken</code> objects owned by the same account.
|
||||
The [NFTokenPage object][] contains a set of `NFToken` objects owned by the same account.
|
||||
|
||||
You create a new `NFToken` using the <code>[NFTokenMint](references/protocol-reference/ledger-data/ledger-object-types/nftokenmint.html)</code> transaction
|
||||
You create a new `NFToken` using the [NFTokenMint transaction][].
|
||||
|
||||
<code>[NFTokenOffer](references/protocol-reference/ledger-data/ledger-object-types/nftokenoffer.html)</code> is a new object that describes an offer to buy or sell a single <code>NFToken</code>.
|
||||
[NFTokenOffer object][] is a new object that describes an offer to buy or sell a single `NFToken`.
|
||||
|
||||
You destroy an `NFToken` using the <code>[NFTokenBurn](references/protocol-reference/ledger-data/ledger-object-types/nftokenburn.html)</code> transaction.
|
||||
You destroy an `NFToken` using the [NFTokenBurn transaction][].
|
||||
|
||||
|
||||
## `NFToken` Lifecycle
|
||||
@@ -58,34 +57,27 @@ You create a NFT using the `NFTokenMint` transaction. The `NFToken` lives on the
|
||||
|
||||
|
||||
|
||||
## Extensions
|
||||
|
||||
|
||||
### Objects
|
||||
|
||||
|
||||
|
||||
* <code>[NFToken](references/protocol-reference/ledger-data/ledger-object-types/nftoken.html)</code>
|
||||
* <code>[NFTokenOffer](references/protocol-reference/ledger-data/ledger-object-types/nftokenoffer.html)</code>
|
||||
* <code>[NFTokenPage](references/protocol-reference/ledger-data/ledger-object-types/nftokenpage.html)</code>
|
||||
|
||||
|
||||
### Transactions
|
||||
|
||||
|
||||
|
||||
* <code>[NFTokenMint](references/protocol-reference/transactions/transaction-types/nftokenmint.html)</code>
|
||||
* <code>[NFTokenOffer](references/protocol-reference/transactions/transaction-types/nftokenoffer.html)</code>
|
||||
* <code>[NFTokenCreateOffer](references/protocol-reference/transactions/transaction-types/nftokencreateoffer.html)</code>
|
||||
* <code>[NFTokenCancelOffer](references/protocol-reference/transactions/transaction-types/nftokencanceloffer.html)</code>
|
||||
* <code>[NFTokenAcceptOffer](references/protocol-reference/transactions/transaction-types/nftokenacceptoffer.html)</code>
|
||||
* <code>[NFTokenBurn](references/protocol-reference/transactions/transaction-types/nftokenburn.html)</code>
|
||||
|
||||
|
||||
### Requests
|
||||
## Reference
|
||||
|
||||
- [NFToken][] data type
|
||||
- Ledger Objects
|
||||
- [NFTokenOffer object][]
|
||||
- [NFTokenPage object][]
|
||||
- Transactions
|
||||
- [NFTokenMint transaction][]
|
||||
- [NFTokenCreateOffer transaction][]
|
||||
- [NFTokenCancelOffer transaction][]
|
||||
- [NFTokenAcceptOffer transaction][]
|
||||
- [NFTokenBurn transaction][]
|
||||
|
||||
|
||||
### API Methods
|
||||
|
||||
* `acct_nfts`
|
||||
* `nft_sell_offers`
|
||||
* `nft_buy_offers`
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
---
|
||||
html: nftoken.html
|
||||
parent: nft-concepts.html
|
||||
blurb: Introduction to XRPL NFTs.
|
||||
filters:
|
||||
- include_code
|
||||
labels:
|
||||
- Non-fungible Tokens, NFTs
|
||||
status: not_enabled
|
||||
---
|
||||
# The `NFToken` Object
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
The `NFToken` object represents a single NFT. This is an example of an `NFToken` object in JSON format, consisting of `TokenID` and `URI` fields.
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"TokenID": "000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65",
|
||||
"URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Unlike other objects, `NFToken` has no field to identify the object type or current owner of the object. `NFToken `objects are grouped into `NFTokenPages` that implicitly define the object type and identify the owner.
|
||||
|
||||
|
||||
## TokenID
|
||||
|
||||
TokenID, optional, string, UInt256
|
||||
|
||||
This composite field uniquely identifies a token, and consists of the following sections.
|
||||
|
||||
|
||||
|
||||
1. 16 bits that identify flags or settings specific to the NFT
|
||||
2. 16 bits that encode the transfer fee associated with this token, if any
|
||||
3. A 160-bit account identifier of the issuer
|
||||
4. A 32-bit issuer-specified [taxon](https://www.merriam-webster.com/dictionary/taxon)
|
||||
5. An (automatically generated) monotonically increasing 32-bit sequence number.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The 16-bit flags, transfer fee fields, the 32-bit taxon, and the sequence number fields are stored in big-endian format.
|
||||
|
||||
|
||||
## Flags
|
||||
|
||||
Flags are properties or other options associated with the `NFToken` object.
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Flag Name</strong>
|
||||
</td>
|
||||
<td><strong>Flag Value</strong>
|
||||
</td>
|
||||
<td><strong>Description</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfBurnable</code>
|
||||
</td>
|
||||
<td><code>0x0001</code>
|
||||
</td>
|
||||
<td>If set, indicates that the issuer (or an entity authorized by the issuer) can destroy the object. The object's owner can <em>always</em> do so.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfOnlyXRP</code>
|
||||
</td>
|
||||
<td><code>0x0002</code>
|
||||
</td>
|
||||
<td>If set, indicates that the tokens can only be offered or sold for XRP.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfTrustLine</code>
|
||||
</td>
|
||||
<td><code>0x0004</code>
|
||||
</td>
|
||||
<td>If set, indicates that the issuer wants a trustline to be automatically created. The <code>lsfTrustLine</code> field is useful when the token can be offered for sale for assets other than XRP and the issuer charges a <code>TransferFee</code>. If this flag is set, a trust line is automatically created as needed to allow the issuer to receive the appropriate transfer fee. If this flag is not set, an attempt to transfer the NFToken for an asset for which the issuer does not have a trustline fails.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfTransferable</code>
|
||||
</td>
|
||||
<td><code>0x0008</code>
|
||||
</td>
|
||||
<td>If set, indicates that this NFT can be transferred. This flag has no effect if the token is being transferred <em>from</em> the issuer or <em>to</em> the issuer.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfReservedFlag</code>
|
||||
</td>
|
||||
<td><code>0x8000</code>
|
||||
</td>
|
||||
<td>This proposal reserves this flag for future use. Attempts to set this flag fail.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
`NFToken `flags are immutable: they can only be set during the `NFTokenMint` transaction and cannot be changed later.
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
The example sets three flags: lsfBurnable (0x0001), lsfOnlyXRP (0x0002), lsfTransferable (0x0008). 1+2+8 = 11, or 0x000B in big endian format.
|
||||
|
||||

|
||||
|
||||
|
||||
### TransferFee
|
||||
|
||||
The TransferFee value specifies the percentage fee, in units of 1/10,000, charged by the issuer for secondary sales of the token. Valid values for this field are between 0 and 50,000, inclusive. A value of 1 is equivalent to 1bps or 0.01%, allowing transfer rates between 0% and 50%.
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
This value sets the transfer fee to 314 bps, or 3.14%.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### Issuer Identification
|
||||
|
||||
The third section of the TokenID is a big endian representation of the issuer’s public address.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### Taxon
|
||||
|
||||
The fourth section is a taxon created by the issuer.
|
||||
|
||||

|
||||
|
||||
An issuer might issue several NFTs with the same taxon; to ensure that NFTs are spread across multiple pages, the taxon is scrambled using the fifth section, a dumb sequential number, as the seed for a random number generator. The scrambled value is stored with the `NFToken`, but the unscrambled value is the actual taxon.
|
||||
|
||||

|
||||
|
||||
Notice that the scrambled version of the taxon is `0xBC8B858E`: the scrambled version of the taxon specified by the issuer. But the _actual_ value of the taxon is the unscrambled value.
|
||||
|
||||
|
||||
|
||||
## URI
|
||||
|
||||
The URI field points to the data and/or metadata associated with the `NFToken`. This field need not be an HTTP or HTTPS URL; it could be an IPFS URI, a magnet link, immediate data encoded as an RFC2379 ["data" URL](https://datatracker.ietf.org/doc/html/rfc2397), or even an opaque issuer-specific encoding. The URI is not checked for validity, but the field is limited to a maximum length of 256 bytes.
|
||||
|
||||
One drawback of using this method is that the value is immutable, so it commits the issuer to hosting the data in perpetuity.
|
||||
|
||||
|
||||
# Retrieving `NFToken` Data and Metadata
|
||||
|
||||
To minimize the footprint of `NFTokens` without sacrificing functionality or imposing unnecessary restrictions, XRPL NFTs do not have arbitrary data fields. Instead, data is maintained separately and referenced by the `NFToken`. The URI provides a reference to immutable content for the `Hash` and any mutable data for the `NFToken` object.
|
||||
|
||||
The `URI` field is especially useful for referring to non-traditional Peer-to-Peer (P2P) URLs. For example, a `minter` that stores `NFToken` data or metadata using the Inter Planetary File System (IPFS) can use the `URI` field to refer to data on IPFS in different ways, each of which is suited to different use-cases. For more context on types of IPFS links that can be used to store NFT data, see [Best Practices for Storing NFT Data using IPFS](https://docs.ipfs.io/how-to/best-practices-for-nft-data/#types-of-ipfs-links-and-when-to-use-them),
|
||||
|
||||
An alternative to the URI approach is for issuers of `NFToken` objects to set the `Domain` field of their issuing account to the correct domain, and offer an API for clients that want to lookup the data or metadata associated with a particular `NFToken`. Note that using this mechanism _requires_ the `minter` to acquire a domain name and set the domain name for their minting account, but does not require the `minter` to necessarily operate a server nor other service to provide the ability to query this data; instead, a `minter` can "redirect" queries to a data provider (for example, to a marketplace, registry or other service).
|
||||
|
||||
Your implementation should first attempt to check for the presence of the `URI` field to retrieve the associated data and/or metadata. If the `URI` field does not exist, the implementation should check for the presence of `Domain` field. If neither field exists, nothing happens. Implementations must be prepared to handle HTTP redirections (for example, using HTTP responses 301, 302, 307 and 308) from the URI.
|
||||
|
||||
|
||||
## TXT Record Format
|
||||
|
||||
The format for a text record is as follows.
|
||||
|
||||
|
||||
```
|
||||
xrpl-nft-data-token-info-v1 IN TXT "https://host.example.com/api/token-info/{:tokenid:}"
|
||||
```
|
||||
|
||||
|
||||
Replace the string `{:tokenid:}` with the requested token’s `TokenID` as a 64-byte hex string when you attempt to query information.
|
||||
|
||||
Your implementation should check for the presence of `TXT` records and use those query strings if present. If no string is present, implementations should attempt to use a default URL. Assuming the domain is _example.com_, the default URL would be:
|
||||
|
||||
|
||||
```
|
||||
https://example.com/.well-known/xrpl-nft/{:tokenid:}
|
||||
```
|
||||
|
||||
|
||||
You create NFTs using the `NFTokenMint` transaction. You can optionally destroy NFTokens using the `NFTokenBurn` transaction.
|
||||
@@ -1,139 +0,0 @@
|
||||
---
|
||||
html: nftokenburn.html
|
||||
parent: nft-concepts.html
|
||||
blurb: Use TokenBurn to permanently destroy NFTs.
|
||||
filters:
|
||||
- include_code
|
||||
labels:
|
||||
- Non-fungible Tokens, NFTs
|
||||
status: not_enabled
|
||||
---
|
||||
# The `NFTokenBurn` Transaction
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
The `NFTokenBurn` transaction is used to remove a `NFToken` object from the `NFTokenPage` in which it is being held, effectively removing the token from the ledger (_burning_ it).
|
||||
|
||||
If this operation succeeds, the corresponding `NFToken` is removed. If this operation empties the `NFTokenPage` holding the `NFToken` or results in consolidation, thus removing a `NFTokenPage`, the owner’s reserve requirement is reduced by one.
|
||||
|
||||
|
||||
## Example `NFTokenBurn` JSON
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"TransactionType": "NFTokenBurn",
|
||||
"Account": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"Fee": 10,
|
||||
"TokenID": "000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## NFTokenBurn Transaction 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>TransactionType</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt16
|
||||
</td>
|
||||
<td>The <code>NFTokenBurn</code> transaction type. The integer value is <code>26</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Account</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>Account ID
|
||||
</td>
|
||||
<td>The <code>AccountID</code> that submitted this transaction. The account must be either the present <code>owner</code> of the token or, if the <code>lsfBurnable</code> flag is set in the <code>NFToken</code>, the <code>issuer</code> account or an account authorized by the issuer, (that is, the <code>MintAccount</code>).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TokenID</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt256
|
||||
</td>
|
||||
<td>Identifies the <code>NFToken</code> object to be removed by the transaction.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
## Account Root Enhancements
|
||||
|
||||
|
||||
### `MintAccount`
|
||||
|
||||
|
||||
Issuers might want to issue NFTs from their well known account, while at the same time wanting to delegate the issuance of such NFTs to a mint or other third party.
|
||||
|
||||
|
||||
<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>MintAccount</code>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>Account ID
|
||||
</td>
|
||||
<td>The <code>MintAccount</code> field, if set, specifies an alternate account which is allowed to execute the <code>NFTokenMint</code> and <code>NFTokenBurn</code> operations on behalf of the account.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
The `SetAccount` transaction allows the `MintAccount` field to be set or cleared.
|
||||
|
||||
### `MintedTokens`
|
||||
|
||||
|
||||
The `MintedTokens` field is used to form the `TokenID` of a new object, to ensure the uniqueness of `NFToken` objects. If this field is not present, the value is 0.
|
||||
|
||||
|
||||
### `BurnedTokens`
|
||||
|
||||
|
||||
The `BurnedTokens` field provides a convenient way to determine how many `NFToken` objects issued by an account are still active (that is, not burned). If this field is not present the value 0 is assumed. The field is decremented whenever a token issued by this account is burned.
|
||||
|
||||
An account for which the difference the number of minted and burned tokens, as stored in the `MintedTokens` and `BurnedTokens` fields respectively, is non-zero cannot be deleted.
|
||||
@@ -1,215 +0,0 @@
|
||||
---
|
||||
html: nftokenmint.html
|
||||
parent: nft-concepts.html
|
||||
blurb: Use TokenMint to issue new NFTs.
|
||||
filters:
|
||||
- include_code
|
||||
labels:
|
||||
- Non-fungible Tokens, NFTs
|
||||
status: not_enabled
|
||||
---
|
||||
# The `NFTokenMint` Transaction
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
The `NFTokenMint` transaction creates a `NFToken` object and adds it to the relevant `NFTokenPage` object of the `minter`. A required parameter to this transaction is the `Token` field specifying the actual token. This transaction is the only opportunity the `minter` has to specify any token fields that are defined as immutable (for example, the `TokenFlags`).
|
||||
|
||||
If the transaction is successful, the newly minted token is owned by the account (the `minter` account) that executed the transaction. If needed, the server creates a new `NFTokenPage` for the account and applies a reserve charge.
|
||||
|
||||
|
||||
## Example `NFTokenMint` transaction
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"TransactionType": "NFTokenMint",
|
||||
"Account": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"Issuer": "rNCFjv8Ek5oDrNiMJ3pw6eLLFtMjZLJnf2",
|
||||
"TransferFee": 314,
|
||||
"Flags": 2147483659,
|
||||
"Fee": 10,
|
||||
"URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi"
|
||||
"Memos": [
|
||||
{
|
||||
"Memo": {
|
||||
"MemoType":
|
||||
"687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E65726963",
|
||||
"MemoData": "72656E74"
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
This transaction assumes that the issuer, `rNCFjv8Ek5oDrNiMJ3pw6eLLFtMjZLJnf2`, has set the `MintAccount` field in its `AccountRoot` to `rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B`, thereby authorizing that account to mint tokens on its behalf.
|
||||
|
||||
|
||||
## **Execution**
|
||||
|
||||
|
||||
In executing, this transaction examines the `MintedTokens` field in the account root of the `Issuer` and uses it to construct the `TokenID` for the token being minted. If the field does not exist, the field is assumed to have the value 0; the value of the field is then incremented by exactly 1.
|
||||
|
||||
|
||||
## Transaction-specific Fields
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Field Name
|
||||
</td>
|
||||
<td>Required?
|
||||
</td>
|
||||
<td>JSON Type
|
||||
</td>
|
||||
<td>Internal Type
|
||||
</td>
|
||||
<td>Description
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TransactionType</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td><code>string</code>
|
||||
</td>
|
||||
<td><code>UInt16</code>
|
||||
</td>
|
||||
<td>Indicates the new transaction type <code>NFTokenMint</code>. The integer value is <code>25</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Account</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td><code>string</code>
|
||||
</td>
|
||||
<td><code>AccountID</code>
|
||||
</td>
|
||||
<td>Indicates the account that is minting the token. The account MUST <em>either</em>:
|
||||
<ul>
|
||||
|
||||
<li>match the <code>Issuer</code> field in the <code>NFToken</code> object; or
|
||||
|
||||
<li>match the <code>MintAccount</code> field in the <code>AccountRoot</code> of the <code>Issuer</code> field in the <code>NFToken</code> object.
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Issuer</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td><code>string</code>
|
||||
</td>
|
||||
<td><code>AccountID</code>
|
||||
</td>
|
||||
<td>Indicates the account that issues the token. This value is <em>optional</em> and should only be specified if the account executing the transaction is not the <code>Issuer</code> of the <code>NFToken</code> object. If it is present, the <code>MintAccount</code> field in the <code>AccountRoot</code> of the <code>Issuer</code> field must match the <code>Account</code>. Otherwise, the transaction fails.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TokenTaxon</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td><code>number</code>
|
||||
</td>
|
||||
<td><code>UInt32</code>
|
||||
</td>
|
||||
<td>The taxon associated with the token. The taxon is generally a value chosen by the <code>minter</code> of the token. A given taxon can be used for multiple tokens. This implementation reserves all taxon identifiers greater than or equal to <code>0x80000000</code>; attempts to use mint tokens with such taxons should fail and a fee should be claimed.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TransferFee</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td><code>number</code>
|
||||
</td>
|
||||
<td><code>UInt16</code>
|
||||
</td>
|
||||
<td>The value specifies the fee charged by the issuer for secondary sales of the Token, if such sales are allowed. Valid values for this field are between 0 and 9999 inclusive, allowing transfer rates of between 0.00% and 99.99% in increments of 0.01.
|
||||
<p>
|
||||
The field MUST NOT be present if <code>tfTransferable</code> is not set. If it is, the transaction should fail and the server should claim a fee.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>URI</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td><code>string</code>
|
||||
</td>
|
||||
<td><code>BLOB</code>
|
||||
</td>
|
||||
<td>A URI that points to the data or metadata associated with the NFT. This field need not be an HTTP or HTTPS URL; it could be an IPFS URI, a magnet link, immediate data encoded as an RFC2379 <a href="https://datatracker.ietf.org/doc/html/rfc2397">"data" URL</a>, or even an opaque issuer-specific encoding. The URI is NOT checked for validity, but the field is limited to a maximum length of 256 bytes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Flags</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td><code>number</code>
|
||||
</td>
|
||||
<td><code>UInt32</code>
|
||||
</td>
|
||||
<td>Specifies the flags used for the minting transaction. See the mint transaction flags in the following table.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
### Mint Transaction Flags
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Flag Name</strong>
|
||||
</td>
|
||||
<td><strong>Flag Value</strong>
|
||||
</td>
|
||||
<td><strong>Description</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tfBurnable</code>
|
||||
</td>
|
||||
<td><code>0x00000001</code>
|
||||
</td>
|
||||
<td>If set, indicates that the <code>lsfBurnable</code> flag should be set.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tfOnlyXRP</code>
|
||||
</td>
|
||||
<td><code>0x00000002</code>
|
||||
</td>
|
||||
<td>If set, indicates that the <code>lsfOnlyXRP</code> flag should be set.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tfTrustLine</code>
|
||||
</td>
|
||||
<td><code>0x00000004</code>
|
||||
</td>
|
||||
<td>If set, indicates that the <code>lsfTrustLine</code> flag should be set.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tfTransferable</code>
|
||||
</td>
|
||||
<td><code>0x00000008</code>
|
||||
</td>
|
||||
<td>If set, indicates that the <code>lsfTransferable</code> flag should be set.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
## Embedding additional information
|
||||
|
||||
If you need to specify additional information during minting (for example, details identifying a property by referencing a particular [plat](https://en.wikipedia.org/wiki/Plat), a vehicle by specifying a [VIN](https://en.wikipedia.org/wiki/Vehicle_identification_number), or other object-specific descriptions) you can use the <code>[memo](https://xrpl.org/transaction-common-fields.html#memos-field)</code> functionality already available on the XRP Ledger as a common field. Memos are a part of the signed transaction and are available from historical archives, but are not stored in the ledger.
|
||||
@@ -1,645 +0,0 @@
|
||||
---
|
||||
html: nftokenoffer.html
|
||||
parent: nft-concepts.html
|
||||
blurb: Create offers to buy or sell NFTs.
|
||||
filters:
|
||||
- include_code
|
||||
labels:
|
||||
- Non-fungible Tokens, NFTs
|
||||
status: not_enabled
|
||||
---
|
||||
# The `NFTokenOffer` Ledger Entry
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
Tokens that have the `lsfTransferable` flag set can be transferred among participants using offers.
|
||||
|
||||
|
||||
## The `NFTokenOffer` ledger entry
|
||||
|
||||
The `NFTokenOffer` ledger entry represents an offer to buy, sell or transfer an `NFToken` object. The owner of a `NFToken` can use `NFTokenCreateOffer` to start a transaction.
|
||||
|
||||
|
||||
### `NFTokenOfferID` Format
|
||||
|
||||
The unique ID (`NFTokenOfferID)` of the `NFTokenOffer` object is the result of the following values concatenated in order:
|
||||
|
||||
|
||||
|
||||
* The `NFTokenOffer` space key, `0x0074`;
|
||||
* The `AccountID` of the account placing the offer; and
|
||||
* The `Sequence` (or `Ticket`) of the `NFTokenCreateOffer` transaction that will create the `NFTokenOffer`.
|
||||
|
||||
|
||||
### `NFTokenOffer` 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>Owner</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>AccountID
|
||||
</td>
|
||||
<td><code>Owner</code> of the account that is creating and owns the offer. Only the current <code>Owner</code> of an <code>NFToken</code> can create an offer to sell an <code>NFToken</code>, but any account can create an offer to buy an <code>NFToken</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>LedgerEntryType</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt16
|
||||
</td>
|
||||
<td>The type of ledger object (<code>0x0074</code>).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>PreviousTxnID</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>Hash256
|
||||
</td>
|
||||
<td>Identifying hash of the transaction that most recently modified this object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>PreviousTxnLgrSeq</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>number
|
||||
</td>
|
||||
<td>UInt32
|
||||
</td>
|
||||
<td>Index of the ledger that contains the transaction that most recently modified this object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TokenID</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt256
|
||||
</td>
|
||||
<td><code>TokenID</code> of the <code>NFToken</code> object referenced by this offer.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Amount</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>object or string
|
||||
</td>
|
||||
<td>AMOUNT
|
||||
</td>
|
||||
<td>Amount expected or offered for the <code>NFToken</code>. If the token has the <code>lsfOnlyXRP</code> flag set, the amount must be specified in XRP.
|
||||
<p>
|
||||
Sell offers that specify assets other than XRP must specify a non-zero amount. Sell offers that specify XRP can be 'free' (that is, the <code>Amount</code> field can be equal to <code>"0"</code>).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Expiration</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>number
|
||||
</td>
|
||||
<td>UInt32
|
||||
</td>
|
||||
<td>The time after which the offer is no longer active. The value is the number of seconds since the <a href="https://xrpl.org/basic-data-types.html#specifying-time">Ripple Epoch</a>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Destination</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>Account ID
|
||||
</td>
|
||||
<td>The <code>AccountID</code> for which this offer is intended. If present, only that account can accept the offer.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>OwnerNode</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt64
|
||||
</td>
|
||||
<td>Internal bookkeeping, indicating the page inside the owner directory where this token is being tracked. This field allows the efficient deletion of offers.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>OfferNode</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt64
|
||||
</td>
|
||||
<td>Internal bookkeeping, indicating the page inside the token buy or sell offer directory, as appropriate, where this token is being tracked. This field allows the efficient deletion of offers.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Flags</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>number
|
||||
</td>
|
||||
<td>UInt32
|
||||
</td>
|
||||
<td>A set of flags associated with this object, used to specify various options or settings. Flags are listed in the table below.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
#### NFTokenOffer Flags
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Flag Name</strong>
|
||||
</td>
|
||||
<td><strong>Flag Value</strong>
|
||||
</td>
|
||||
<td><strong>Description</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfBuyToken</code>
|
||||
</td>
|
||||
<td><code>0x00000001</code>
|
||||
</td>
|
||||
<td>If set, the offer is a buy offer. Otherwise, the offer is a sell offer.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>lsfAuthorized</code>
|
||||
</td>
|
||||
<td><code>0x00000002</code>
|
||||
</td>
|
||||
<td>If set, the offer has been approved by the issuer. This flag can only be set by the <code>Issuer</code> of the token or an account authorized by the issuer (for example, the <code>MintAccount</code> listed in the account root of the <code>Issuer</code>) and only if the token has the flag indicating that authorization is required.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
## `NFTokenOffer` Transactions
|
||||
|
||||
Token offers on XRPL are stored sorted by quality in an order book and automatically matched by an on-ledger mechanism. An `NFTokenOffer` is not stored in an order book and is never automatically matched or executed.
|
||||
|
||||
A buyer must _explicitly_ choose to accept an `NFTokenOffer` that offers to buy an `NFToken`. Similarly, a seller must _explicitly_ choose to accept a specific `NFTokenOffer` that offers to buy an `NFToken` object that they own.
|
||||
|
||||
|
||||
### Locating `NFTokenOffer` objects
|
||||
|
||||
Each token has two directories. One contains offers to buy the token and the other containing offers to sell the token. This makes it easy to find `NFTokenOffer` for a particular token. It is expected that off-ledger systems will be used to retrieve, present, communicate and effectuate the creation, enumeration, acceptance or cancellation of offers. For example, a marketplace may offer intuitive web- or app-based interfaces for users.
|
||||
|
||||
|
||||
### `NFTokenOffer` Reserve
|
||||
|
||||
Each `NFTokenOffer` object costs the account placing the offer one incremental reserve. As of this writing the incremental reserve is 5 XRP. The reserve can be recovered by cancelling the offer.
|
||||
|
||||
|
||||
### `NFTokenOffer` Transactions
|
||||
|
||||
There are three defined transactions:
|
||||
|
||||
|
||||
|
||||
1. `NFTokenCreateOffer`
|
||||
|
||||
|
||||
2. `NFTokenCancelOffer`
|
||||
|
||||
|
||||
3. `NFTokenAcceptOffer`
|
||||
All three transactions have the generic set of transaction fields.
|
||||
|
||||
|
||||
### `NFTokenCreateOffer` transaction
|
||||
|
||||
The `NFTokenCreateOffer` transaction creates either a new _Sell_ offer for an `NFToken` owned by the account executing the transaction, or a new _Buy_ offer for an `NFToken` owned by another account.
|
||||
|
||||
Each offer costs one incremental reserve.
|
||||
|
||||
|
||||
#### `NFTokenCreateOffer` 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>TransactionType</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt16
|
||||
</td>
|
||||
<td>Indicates the new transaction type <code>NFTokenCreateOffer</code>. The integer identifier is <code>27</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Account</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>AccountID
|
||||
</td>
|
||||
<td>Indicates the <code>AccountID</code> of the account that initiated the transaction.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Owner</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>Account ID
|
||||
</td>
|
||||
<td>Indicates the <code>AccountID</code> of the account that owns the corresponding <code>NFToken</code>.
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
If the offer is to buy a token, this field must be present and it must be different than <code>Account</code> (since an offer to buy a token one already holds is meaningless).
|
||||
|
||||
<li>If the offer is to sell a token, this field must not be present, as the owner is, implicitly, the same as <code>Account</code> (since an offer to sell a token one doesn't already hold is meaningless).
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TokenID</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>Hash256
|
||||
</td>
|
||||
<td>Identifies the <code>TokenID</code> of the <code>NFToken</code> object that the offer references.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Amount</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>Currency Amount
|
||||
</td>
|
||||
<td>AMOUNT
|
||||
</td>
|
||||
<td>Indicates the amount expected or offered for the <code>Token</code>.
|
||||
<p>
|
||||
The amount must be non-zero, except where this is an offer to sell and the asset is XRP; then, it is legal to specify an amount of zero, which means that the current owner of the token is giving it away, gratis, either to anyone at all, or to the account identified by the <code>Destination</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Expiration</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>number
|
||||
</td>
|
||||
<td>UInt32
|
||||
</td>
|
||||
<td>Indicates the time after which the offer will no longer be valid. The value is the number of seconds since the <a href="https://xrpl.org/basic-data-types.html#specifying-time">Ripple Epoch</a>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Destination</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>AccountID
|
||||
</td>
|
||||
<td>If present, indicates that this offer may only be accepted by the specified account. Attempts by other accounts to accept this offer MUST fail.
|
||||
<p>
|
||||
If succesful, <code>NFTokenCreateOffer</code> transaction results in the creation of <code>NFTokenOffer</code> object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Flags</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>number
|
||||
</td>
|
||||
<td>UInt32
|
||||
</td>
|
||||
<td>A set of flags that specifies options or controls the behavior of the transaction. The flag is defined in the table below.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
#### `NFTokenCreateOffer` Flags
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Flag Name</strong>
|
||||
</td>
|
||||
<td><strong>Flag Value</strong>
|
||||
</td>
|
||||
<td><strong>Description</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>tfSellToken</code>
|
||||
</td>
|
||||
<td><code>0x00000001</code>
|
||||
</td>
|
||||
<td>If set, indicates that the offer is a sell offer. Otherwise, it is a buy offer.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
Note that the `Flags` field includes both transaction-specific and generic flags; all currently valid generics flags (for example, `tfFullyCanonicalSig`) are applicable, but not listed here.
|
||||
|
||||
The transactor does not allow unknown flags to be set.
|
||||
|
||||
|
||||
## `NFTokenCancelOffer` transaction
|
||||
|
||||
The `NFTokenCancelOffer` transaction can be used to cancel existing token offers created using `NFTokenCreateOffer`.
|
||||
|
||||
|
||||
### Permissions
|
||||
|
||||
An existing offer, represented by an `NFTokenOffer` object, can be cancelled by:
|
||||
|
||||
|
||||
|
||||
* The account that originally created the `NFTokenOffer`.
|
||||
* The account in the `Destination` field of the `NFTokenOffer`, if one is present.
|
||||
* The issuer of the token identified by the `TokenUID` field in the `NFTokenOffer` object, if the token has the `lsfIssuerCanCancelOffers` flag set.
|
||||
* Any account, if the `NFTokenOffer` specifies an expiration time and the close time of the parent ledger in which the `NFTokenCancelOffer` is included is greater than the expiration time.
|
||||
|
||||
This transaction removes the listed `NFTokenOffer` object from the ledger, if present, and adjusts the reserve requirements accordingly. It is not an error if the `NFTokenOffer` cannot be found: if that is the case, the transaction should complete successfully.
|
||||
|
||||
|
||||
### `NFTokenCancelOffer` Fields
|
||||
|
||||
An `NFTokenCancelOffer` 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>TransactionType</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt16
|
||||
</td>
|
||||
<td><code>NFTokenCancelOffer</code> transaction type . The integer identifier is <code>28</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TokenIDs</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>array
|
||||
</td>
|
||||
<td>VECTOR256
|
||||
</td>
|
||||
<td>An array of <code>TokenID</code> objects, each identifying the <code>NFTokenOffer</code> object that should be cancelled by this transaction.
|
||||
<p>
|
||||
It is an error if an entry in this list points to an object that is not an <code>NFTokenOffer</code> object. It is not an error if an entry in this list points to an object that does not exist.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
## `NFTokenAcceptOffer` transaction
|
||||
|
||||
The `NFTokenAcceptOffer` transaction is used to accept offers to `buy` or `sell` an `NFToken`. It can either:
|
||||
|
||||
|
||||
|
||||
* Allow one offer to be accepted. This is called _direct_ mode.
|
||||
* Allow two distinct offers, one offering to buy a given `NFToken` and the other offering to sell the same `NFToken`, to be accepted in an atomic fashion. This is called _brokered_ mode.
|
||||
|
||||
|
||||
### Brokered vs. Direct Mode
|
||||
|
||||
The mode in which the transaction operates depends on the presence of the `SellOffer` and `BuyOffer` fields of the transaction:
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong><code>SellOffer</code></strong>
|
||||
</td>
|
||||
<td><strong><code>BuyOffer</code></strong>
|
||||
</td>
|
||||
<td><strong>Mode</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>✔️
|
||||
</td>
|
||||
<td>✔️
|
||||
</td>
|
||||
<td>Brokered
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>✔️
|
||||
</td>
|
||||
<td><B>X</B>
|
||||
</td>
|
||||
<td>Direct
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><B>X</B>
|
||||
</td>
|
||||
<td>✔️
|
||||
</td>
|
||||
<td>Direct
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
If neither of those fields is specified, the transaction is malformed and produces a `tem` class error.
|
||||
|
||||
The semantics of brokered mode are slightly different than one in direct mode: The account executing the transaction functions as a broker, bringing the two offers together and causing them to be matched, but does not acquire ownership of the involved NFT, which will, if the transaction is successful, be transferred directly from the seller to the buyer.
|
||||
|
||||
|
||||
### Execution Details
|
||||
|
||||
|
||||
#### Direct Mode
|
||||
|
||||
In direct mode, `NFTokenAcceptOffer` transaction fails if:
|
||||
|
||||
|
||||
|
||||
* The `NFTokenOffer` against which `NFTokenAcceptOffer` transaction is placed is an offer to `buy `the `NFToken` and the account executing the `NFTokenAcceptOffer` is not, at the time of execution, the current owner of the corresponding `NFToken`.
|
||||
* The `NFTokenOffer` against which `NFTokenAcceptOffer` transaction is placed is an offer to `sell `the `NFToken` and was placed by an account which is not, at the time of execution, the current owner of the `NFToken`
|
||||
* The `NFTokenOffer` against which `NFTokenAcceptOffer` transaction is placed is an offer to `sell `the `NFToken` and was placed by an account which is not, at the time of execution, the `Account` in the recipient field of the `NFTokenOffer`, if there exist one.
|
||||
* The `NFTokenOffer` against which `NFTokenAcceptOffer` transaction is placed specifies an `expiration` time and the close time field of the parent of the ledger in which the transaction would be included has already passed.
|
||||
* The `NFTokenOffer` against which `NFTokenAcceptOffer` transaction is placed to buy or sell the `NFToken `is owned by the account executing the `NFTokenAcceptOffer`.
|
||||
|
||||
A side-effect of such failures is the removal of the `NFTokenOffer` object and the refund of the incremental reserve as if the offer had been cancelled. This necessitates the use of an appropriate `tec` class error.
|
||||
|
||||
If the transaction is executed successfully then:
|
||||
|
||||
* The relevant `NFTtoken` changes ownership, meaning that the token is removed from the `NFTokenPage` of the existing `owner` and added to the `NFTokenPage` of the new `owner`.
|
||||
* Funds are transferred from the buyer to the seller, as specified in the `NFTokenOffer`. If the corresponding `NFToken` offer specifies a `TransferRate`, then the `issuer` receives the specified percentage, with the balance going to the seller of the `NFToken`.
|
||||
|
||||
|
||||
#### Brokered Mode
|
||||
|
||||
In brokered mode, the `NFTokenAcceptOffer` transaction fails if:
|
||||
|
||||
|
||||
|
||||
* The `buy` `NFTokenOffer` against which the `NFTokenAcceptOffer` transaction is placed is owned by the account executing the transaction.
|
||||
* The `sell` `NFTokenOffer` against which the `NFTokenAcceptOffer` transaction is placed is owned by the account executing the transaction.
|
||||
* The account that placed the offer to sell the `NFToken` is not, at the time of execution, the current owner of the corresponding `NFToken`.
|
||||
* Either offer (`buy` or `sell`) specifies an `expiration` time and the close time field of the parent of the ledger in which the transaction would be included has already passed.
|
||||
|
||||
|
||||
### 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>TransactionType</code>
|
||||
</td>
|
||||
<td>Yes
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt16
|
||||
</td>
|
||||
<td>Transaction type <code>NFTokenAcceptOffer</code>. The sequence number of a previous <code>NFTokenCreateOffer</code> transaction. The integer identifier is <code>29</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>SellOffer</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt256
|
||||
</td>
|
||||
<td>Identifies the <code>NFTokenOffer</code> that offers to sell the <code>NFToken</code>.
|
||||
<p>
|
||||
In direct mode this field is optional, but you must specify either the <code>SellOffer</code> or the <code>BuyOffer</code>. In brokered mode, you must specify both the <code>SellOffer</code> and the <code>BuyOffer</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>BuyOffer</code>
|
||||
</td>
|
||||
<td>No
|
||||
</td>
|
||||
<td>string
|
||||
</td>
|
||||
<td>UInt256
|
||||
</td>
|
||||
<td>Identifies the <code>NFTokenOffer</code> that offers to buy the <code>NFToken</code>.
|
||||
<p>
|
||||
In direct mode, this field is optional, but you must specify either the <code>SellOffer</code> or the <code>BuyOffer</code>. In brokered mode, you must specify both the <code>SellOffer</code> and the <code>BuyOffer</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>BrokerFee</code>
|
||||
</td>
|
||||
<td>no
|
||||
</td>
|
||||
<td>object or string
|
||||
</td>
|
||||
<td>Amount
|
||||
</td>
|
||||
<td>This field is only valid in brokered mode, and specifies the amount that the broker keeps as part of their fee for bringing the two offers together; the remaining amount is sent to the seller of the <code>NFToken</code> being bought. If specified, the fee must be such that, prior to accounting for the transfer fee charged by the issuer, the amount that the seller would receive is at least as much as the amount indicated in the sell offer.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
This functionality is intended to allow the `owner` of an `NFToken` to offer their token for sale to a third party broker, who may then attempt to sell the `NFToken` on for a larger amount, without the broker having to own the `NFToken` or custody funds.
|
||||
|
||||
If both offers are for the same asset, it is possible that the order in which funds are transferred might cause a transaction that would succeed to fail due to an apparent lack of funds. To ensure deterministic transaction execution and maximize the chances of successful execution, the account attempting to buy the `NFToken` is debited first. Funds due to the broker are credited _before_ crediting the seller.
|
||||
|
||||
In brokered mode, The offers referenced by `BuyOffer` and `SellOffer` must both specify the same `TokenID`; that is, both must be for the same `NFToken`.
|
||||
@@ -1,237 +0,0 @@
|
||||
---
|
||||
html: nftokenpage.html
|
||||
parent: nft-concepts.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).
|
||||
|
||||
The following is an example `NFTokenPage` object in JSON format.
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"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.
|
||||
|
||||
|
||||
## 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 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>
|
||||
@@ -1,21 +1,19 @@
|
||||
---
|
||||
html: nftoken.html
|
||||
parent: ledger-object-types.html
|
||||
parent: basic-data-types.html
|
||||
blurb: Introduction to XRPL NFTs.
|
||||
filters:
|
||||
- include_code
|
||||
labels:
|
||||
- Non-fungible Tokens, NFTs
|
||||
- Non-fungible Tokens, NFTs
|
||||
status: not_enabled
|
||||
---
|
||||
# NFToken
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
The `NFToken` object represents a single non-fungible token.
|
||||
The `NFToken` object represents a single non-fungible token (NFT). It is not stored on its own, but is contained in a [NFTokenPage object][] alongside other NFTs.
|
||||
|
||||
Example {{currentpage.name}} JSON
|
||||
|
||||
```
|
||||
```json
|
||||
{
|
||||
"TokenID": "000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65",
|
||||
"URI": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi"
|
||||
@@ -32,8 +30,6 @@ TokenID, optional, string, Hash256
|
||||
|
||||
This composite field uniquely identifies a token, and consists of the following sections.
|
||||
|
||||
|
||||
|
||||
1. 16 bits that identify flags or settings specific to the NFT
|
||||
2. 16 bits that encode the transfer fee associated with this token, if any
|
||||
3. A 160-bit account identifier of the issuer
|
||||
@@ -137,7 +133,7 @@ The third section of the TokenID is a big endian representation of the issuer’
|
||||
|
||||
### Taxon
|
||||
|
||||
The fourth section is a taxon created by the issuer.
|
||||
The fourth section is a taxon created by the issuer.
|
||||
|
||||

|
||||
|
||||
@@ -173,17 +169,17 @@ The format for a text record is as follows.
|
||||
|
||||
|
||||
```
|
||||
xrpl-nft-data-token-info-v1 IN TXT "https://host.example.com/api/token-info/{:tokenid:}"
|
||||
xrpl-nft-data-token-info-v1 IN TXT "https://host.example.com/api/token-info/{tokenid}"
|
||||
```
|
||||
|
||||
|
||||
Replace the string `{:tokenid:}` with the requested token’s `TokenID` as a 64-byte hex string when you attempt to query information.
|
||||
Replace the string `{tokenid}` with the requested token’s `TokenID` as a 64-byte hex string when you attempt to query information.
|
||||
|
||||
Your implementation should check for the presence of `TXT` records and use those query strings if present. If no string is present, implementations should attempt to use a default URL. Assuming the domain is _example.com_, the default URL would be:
|
||||
|
||||
|
||||
```
|
||||
https://example.com/.well-known/xrpl-nft/{:tokenid:}
|
||||
https://example.com/.well-known/xrpl-nft/{tokenid}
|
||||
```
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ status: not_enabled
|
||||
# NFTokenMint
|
||||
{% include '_snippets/nfts-disclaimer.md' %}
|
||||
|
||||
The `NFTokenMint` transaction creates a [NFToken object][] and adds it to the relevant [NFTokenPage object][] of the `minter`. A required parameter to this transaction is the `Token` field specifying the actual token. This transaction is the only opportunity the `minter` has to specify any token fields that are defined as immutable (for example, the `TokenFlags`).
|
||||
The `NFTokenMint` transaction creates an non-fungible token and adds it to the relevant [NFTokenPage object][] of the `minter` as an [NFToken][] object. A required parameter to this transaction is the `Token` field specifying the actual token. This transaction is the only opportunity the `minter` has to specify any token fields that are defined as immutable (for example, the `TokenFlags`).
|
||||
|
||||
If the transaction is successful, the newly minted token is owned by the account (the `minter` account) that executed the transaction. If needed, the server creates a new `NFTokenPage` for the account and applies a reserve charge.
|
||||
|
||||
|
||||
@@ -1081,3 +1081,8 @@ value = "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf4dfuylqabf3oclgtqy55fbzdi" siz
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
|
||||
Reference in New Issue
Block a user