前章で、ERC-721 は tokenURI が何を返すべきかを決めていない、と書きました。では実物には何が入っているのでしょうか。開けてみます。

返ってきたもの

tokenURI(1) を呼ぶと、これが返りました。

data:application/json;base64,eyJuYW1lIjoiUFggRGF0YSBORlQiLCJzeW1ib2wiOiJQWC1ORlQi…

http:// でも ipfs:// でもありません。data: で始まる データ URI です。

データ URI は「参照先を指す」のではなく、内容そのものを URI の中に書き込む書き方です。つまりこの JSON は、どこかのサーバや IPFS(分散ファイル保存の仕組み)に置かれているのではなく、チェーン上に直接埋め込まれています。

外部の置き場所に依存しないので、サーバが止まっても内容は失われません。この手法自体は Ocean 固有のものではなく、「完全オンチェーン NFT」として知られています。

デコードすると

base64, 以降を復号すると、こうなっていました。

{
  "name": "PX Data NFT",
  "symbol": "PX-NFT",
  "description": "Data NFTs are unique digital assets that represent the intellectual property of your digital services.",
  "external_url": "https://cliox.org/asset/did:op:89e6023a…befb1",
  "background_color": "ffffff",
  "image": "/images/cliox_text.svg"
}

登録したのは国立国会図書館デジタルコレクションの『歳旦発句牒』です。ところが、この JSON には題名も、機関名も、年代も入っていません

name は「PX Data NFT」。description は「Data NFTs are unique digital assets that…」という一般的な説明文です。変わるのは external_url だけで、他は資産によらず同じ内容になります。

つまりこの JSON は資産の説明ではなく、ウォレットや流通市場に出たときの見た目を用意するためのものです。中身の説明は別のところ(前章までに見たイベントログの中)にあります。

Chain Lens で開く

付属ツールは、この data: URI をその場でデコードして表示します。

「tokenURI の中身」という項目に、形式の判定(データ URI / 外部サーバへのリンク / IPFS へのリンク)と、デコード結果が出ます。他の NFT の取引を入れれば、そちらの形式も判定されます。

これは誰が決めたのか

ここで区別が要ります。data: URI にすることも、定型文を入れることも、Ocean の仕様ではありません。

Ocean の契約は tokenURI を引数として受け取るだけで、値は呼び出し側が決めます。実際、この値を組み立てているのはポータル側のコードでした。

const nftMetadataTemplate = {
  name: 'PX Data NFT',
  symbol: 'PX-NFT',
  description: 'Data NFTs are unique digital assets that represent…',
  external_url: 'https://cliox.org'
}
...
tokenURI: `data:application/json;base64,${encodedMetadata}`

層で整理すると、こうなります。

この件について何を決めているか
ERC-721(規格)URI であること。JSON の推奨書式(name/description/image)はあるが、従う義務はない
Ocean の契約引数として受け取るだけ
ポータルの実装データ URI にする / 定型文を入れる / external_url など市場慣習の項目を足す

PX という接頭辞は Pontus-X というプロジェクトに由来します。今回使ったポータルはその実装をフォークしたもので、テンプレートがそのまま残っているようです。国立国会図書館の資料を登録したのに PX Data NFT と表示され、external_url が別のドメインを指しているのは、この経緯によります。

image が相対パスになっている

もう一点、気になる箇所があります。

"image": "/images/cliox_text.svg"

先頭がスラッシュで始まる相対パスです。通常の Web ページであれば「同じサイトの /images/…」と解決されますが、この JSON はチェーン上のデータ URI の中にあります。基準となるサイトが存在しないので、外部のウォレットや流通市場では画像が解決できないと思われます。

ポータル自身が表示するときは自分のドメインを基準にできるので、そこでは問題になりません。ポータル内でしか意味を持たない書き方になっている、ということのようです。

何を確かめたことになるか

この章でやったのは、tokenURI を 1 つ開けただけです。そこから言えることを整理します。

  • 「NFT は外部の JSON を指す」は、いつも成り立つわけではない。データ URI で内容そのものを載せる形もある
  • tokenURI の中身が資産の説明とは限らない。ここでは表示用の定型文だった
  • どの層が決めているかを区別する必要がある。規格・契約・アプリケーションのどこで決まった値なのかで、他の実装にも当てはまるかが変わる

3 つ目がいちばん実務に効くと思います。「Ocean ではこうなっている」と言うとき、それが規格の要求なのか、Ocean の契約の設計なのか、たまたま使ったポータルの実装なのかで、話の一般性がまったく変わります。

この本でも、以降は層を区別して書きます。

この章で見たこと

  • tokenURIdata: URI で、JSON がチェーン上に埋め込まれていた
  • その JSON には資産固有の情報が入っておらず、表示用の定型文だった
  • これは規格でも Ocean の仕様でもなく、ポータルの実装が決めている
  • image の相対パスは、チェーン上の JSON からは解決できないと思われる

次章では、資産の実際の説明が入っている、暗号化されたほうのデータを見ます。