🔖

EVM と比較しながら XRP Ledger を理解する #3

2024/05/14に公開

本記事の目的

Ethereum Virtual Machine(EVM) の開発経験や知識は多少あるが XRP のことは全く知らない人を主な対象とし、EVM と比較しながら XRP Ledger を理解するシリーズです。コンセンサスアルゴリズムなどの理論にはあまり焦点を当てず、アプリ開発の中で必要になりそうな部分を中心に EVM と比較しながらコンパクトにまとめていこうと思います。

XRP Ledger で NFT を発行

NFT のミント

EVM XRP Ledger
ERC-721 準拠のスマコンを実装 + mint メソッドを実行 NFTokenMint トランザクションを実行

EVM の場合 NFT のミント方法などはスマコンの内容に依るところではありますが、ERC-721 準拠のスマコンを Solidity で実装しネットワークにデプロイ後、mint メソッドを実行することが多いでしょう。
XRP Ledger の場合は NFTokenMint というタイプのトランザクションがプロトコルレベルで実装されているため、それを実行すれだけでミントすることできます。スマコンの実装が不要な分手軽に試せます。
以下は NFT をミントするコードと、その実行結果です。

import { Client, Wallet, convertStringToHex } from "xrpl";


const secret = "sEdVEHTqHPGLY3c5FtsTrNZd2hPXkfF"

const wallet = Wallet.fromSeed(secret);

const client = new Client("wss://testnet.xrpl-labs.com")
await client.connect()

const response = await client.submitAndWait(
  {
    TransactionType: "NFTokenMint",
    Account: wallet.address,
    TransferFee: 10 * 1000,  // 送金手数料を10%に指定
    NFTokenTaxon: 0,
    Flags: 1 + 2 + 8,  // burnable, onlyXRP, transferable
    URI: convertStringToHex("https://xrpl.org/ja/")  // hex 形式に変換
  },
  { wallet }
);
console.log(response)
response
{
  id: 10,
  result: {
    Account: 'rfJsDzdaFpQvZpcvQfjPnByAFrYzJ4eGge',
    Fee: '12',
    Flags: 11,
    LastLedgerSequence: 418242,
    NFTokenTaxon: 0,
    Sequence: 382868,
    SigningPubKey: 'ED65B4987E440C89D48A7F0B2B21E63BE986B2C5652B2D6C1A1D30693DB029609D',
    TransactionType: 'NFTokenMint',
    TransferFee: 10000,
    TxnSignature: '016D9470D1A03247190ACFDBC6351006930C0F9899EBA9559F3EC8B989839FAB3A49DEEFB59EC6D28FA9EB906E4661E673D57D756F07C7B577C1FBFB02C32C03',
    URI: '68747470733A2F2F7872706C2E6F72672F6A612F',
    ctid: 'C00661B000010001',
    date: 768224181,
    hash: '00BB98D0B4875001EF37E2CD86A192DFB3D5CF5F6D931BFEFDA73066DAE907DD',
    inLedger: 418224,
    ledger_index: 418224,
    meta: {
      AffectedNodes: [Array],
      TransactionIndex: 1,
      TransactionResult: 'tesSUCCESS',
      nftoken_id: '000B27104509AEBD50EBDBD96645A1E9D9F3B757CE2FA0E35469B52F0005D794'
    },
    validated: true
  },
  type: 'response'
}

result.meta.nftoken_id にあるように、NFTokenId が 000B27104509AEBD50EBDBD96645A1E9D9F3B757CE2FA0E35469B52F0005D794 の NFT をミントすることができました。とっても簡単です。

NFT の設定や構造

ここから NFT の機能やデータ構造について確認します。

tokenId

EVM XRP Ledger
自動採番などスマコンで定義 パラメータ値から機械的に計算

EVM の場合はスマコンの実装次第で如何様にでもできますが、1番からインクリメントするように定義することが多いでしょうか。
XRP Ledger の tokenId(NFTokenId) は 64 桁の数字で、以下の5項目から生成されます。

A) 16ビットの NFToken のフラグや設定の識別子

NFT を mint する際にバーン可能にするかや、転送できるようにするかなどを指定することができ、その値が NFTokenId の1〜4桁目に該当します。「その他の NFT の設定( SBT 化など)」の項で説明します。

B) 16ビットの NFToken に関連する送金手数料のエンコード化された値(送金手数料が設定されている場合)

EVM では NFT マーケットプレイスのスマコンなどで設定することが多い送金手数料(二次流通の手数料)ですが、XRP Ledger の場合は NFT を mint する際に TransferFee フィールドで二次流通時の NFT 発行者への分配比率を設定することができます。1/100000単位で0から50,000までの値、つまり0%から50%の間で設定が可能です。この値が NFTokenId の5〜8桁目に該当します。

C) 160ビットの発行者のアカウント識別子

NFT の発行者のウォレットアドレスを変換したものです。NFTokenId の9〜48桁目に該当します。尚、発行する際に発行者とは別の所有者を設定することが可能ですが、ここは発行者のアカウント情報が入ります。

D) 32ビットの発行者が指定する NFTokenTaxon

次の「NFTのコレクション化」の項で説明します。NFTokenId の49〜56桁目に該当します。

E) 32ビットの(自動生成される)単調増加するシーケンス番号

NFT の発行者が NFT を作成するたびに1ずつ増加する連番値です。NFTokenId の57〜64桁目に該当します。

https://xrpl.org/ja/docs/references/protocol/data-types/nftoken/#nftokenid

NFTokenId から上記の5項目を取得する

方法はいくつかありますが、xrpl.js であれば parseNFTokenId を使うと簡単に取得することができます。

import { parseNFTokenID } from "xrpl";

const NFTokenId = '000B27104509AEBD50EBDBD96645A1E9D9F3B757CE2FA0E35469B52F0005D794'
console.log(parseNFTokenID(NFTokenId))
parseNFTokenID(NFTokenId)
{
  NFTokenID: '000B27104509AEBD50EBDBD96645A1E9D9F3B757CE2FA0E35469B52F0005D794',
  Flags: 11,
  TransferFee: 10000,
  Issuer: 'rfJsDzdaFpQvZpcvQfjPnByAFrYzJ4eGge',
  Taxon: 0,
  Sequence: 382868
}

NFT のコレクション化(NFTokenTaxon)

EVM XRP Ledger
コントラクトアドレス taxon

EVM の場合多くの NFT はコントラクトアドレスに紐づく形で tokenId が採番されており、マーケットプレイスなどではコントラクトアドレスで検索することでその NFT コレクションを見ることができます。
XRP Ledger の場合はスマコンがありませんので当然コントラクトアドレスも存在しませんが、代わりに NFTokenTaxon という NFT をコレクション化するためのフィールド(UInt32)があります。ミントする際にこのフィールドに何らかの数値を指定することで NFT をコレクション化できるようです。特にコレクション化するつもりがない場合は 0 を指定することが一般的であるようです。
https://xrpl.org/ja/docs/concepts/tokens/nfts/collections/

メタデータ

URI フィールドに最大256バイトの任意のデータを埋め込むことができます。EVM と同じようにデータ URL を埋め込んで on-chain NFT にすることもできますし、外部ストレージを参照する URL を埋め込むことも可能です。

https://xrpl.org/ja/docs/concepts/tokens/nfts/payload-storage/

その他の NFT の設定(SBT 化など)

NFT をミントする際に Flags フィールドにて、以下の項目を設定することが可能です。これらの値はミント後に変更することはできません。

burnable(0x0001)

true の場合、今の所有者が誰かに関わらず発行者または発行者が許可したものであれば NFToken を破棄することができます。(所有者はこのフラグの値にかかわらずいつでも破棄することが可能です。)

onlyXRP(0x0002)

true の場合、XRP でのみ売買が可能です。他の FToken などでは売買ができません。

transferable(0x0008)

false の場合、所有者と発行者の間でのみしか譲渡することができません。SBT に近いものを実現することができます。true の場合は誰にでも譲渡することが可能です。

https://xrpl.org/ja/docs/references/protocol/data-types/nftoken/#nftoken-フラグ

データ構造(NFTokenPage)

EVM XRP Ledger
スマコンでウォレットアドレスと tokenId の mapping を保持 アカウントに紐づく NFTokenPage エントリで tokenId を保持

EVM では誰がどの NFT を持っているかがスマコンが保持しますが、XRP Ledger ではアカウントが保持します。アカウントが所有する NFT はそのアカウントに紐づいた NFTokenPage に格納されます。 1つの NFTokenPage につき最大32個の NFT を格納可能なため、個数によってページは複数生成されます。どのページにどの NFT を格納するかや、ページの生成/削除はプロトコルで定められた方法で自動で行われます。詳しくは以下のドキュメントに記載がありますのでご覧ください。

https://xrpl.org/ja/docs/references/protocol/ledger-data/ledger-entry-types/nftokenpage/


ここでは EVM と比較しながら NFT のミント方法とその設定項目について確認しました。API を1回コールするだけでさまざまな機能を持つ NFT をミントできるので、EVM よりも手軽に発行できることが確認できました。
次回は発行した NFT を送る、売買する方法を取り上げようと思います。

Discussion