1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

10. Composable Resources

Last updated at Posted at 2024-10-31

このチュートリアルでは、複合的なNFTを作成、デプロイ、移動させることで、リソースが他のリソースを所有する方法を説明します。

ⓘ ACTION(操作)
このチュートリアルには、サンプルコードのみが含まれています。関連するプレイグラウンドプロジェクトはありません。ただし、このコードをコピーしてプレイグラウンドに貼り付け、テストすることは可能です。

リソースを所有するリソースは、ブロックチェーンとスマートコントラクトの世界では強力な機能です。

このチュートリアルを進める前に、「Getting Started」、「Hello, World!」、および「Resources」の手順に従って、プレイグラウンドとCadenceについて学んでください。

Resources Owning Resources

非代替トークン(Non-Fungible Tokens)で話題になっているNFTコレクションは、他のリソースを所有するリソースの一例です。NFTコレクションというリソースがあり、その中に保存されているNFTリソースを所有しています。所有者と参照(reference)を持つ人は誰でも、これらのリソースを移動させることができます(補足: 例としてマーケットプレイスのようなスマートコントラクトに所有者が参照を渡しているケースがあります。)が、それらがコレクション内に存在する限り、それらはコレクションに属しており、コレクションで定義されたコードがリソースを最終的に制御します。

コレクションが移動または破棄された場合、その中にあるすべてのNFTも一緒に移動または破棄されます。

コレクションの所有者がコレクションのリソース全体を他のユーザーのアカウントに転送した場合、トークンはすべて他のユーザーのアカウントに移動します。トークンは元の所有者のアカウントには残りません。これは、1ドル紙幣ではなく財布を誰かに手渡すようなものです。一般的ではありませんが、確かに可能です。

他のリソースに格納されているリソースに対しては参照を作成することはできません。 所有するリソースがそれを制御し、したがって、格納されたリソースに対する外部からの呼び出しのアクセス権限を制御します。

Example

NFTコレクションは、リソースが他のリソースを所有できることを示す単純な例ですが、より革新的で強力なバージョンを作成することも可能です。

CryptoKitties(およびイーサリアム・ブロックチェーン上のその他のアプリケーション)の重要な特徴は、既存のアプリケーションの周りに、あらゆる開発者が新しい体験を作り出せることです。オリジナルのスマートコントラクトには、CryptoKittyのアクセサリー(帽子など)に対する具体的なサポートは含まれていませんでしたが、独立した開発者は、オリジナルのスマートコントラクトのKittiesが使える帽子を作ることができました。

以下は、この機能をCadenceで再現する方法の基本的な例です。

// KittyVerse.cdc
//
// The KittyVerse contract defines two types of NFTs.
// One is a KittyHat, which represents a special hat, and
// the second is the Kitty resource, which can own Kitty Hats.
//
// You can put the hats on the cats and then call a hat function
// that tips the hat and prints a fun message.
//
// This is a simple example of how Cadence supports
// extensibility for smart contracts, but the language will soon
// support even more powerful versions of this.
//

access(all) contract KittyVerse {

    // KittyHat is a special resource type that represents a hat
    access(all) resource KittyHat {

        access(all) let id: Int
        
        access(all) let name: String

        init(id: Int, name: String) {
            self.id = id
            self.name = name
        }

        // An example of a function someone might put in their hat resource
        access(all) fun tipHat(): String {
            if self.name == "Cowboy Hat" {
                return "Howdy Y'all"
            } else if self.name == "Top Hat" {
                return "Greetings, fellow aristocats!"
            }

            return "Hello"
        }
    }

    // Create a new hat
    access(all) fun createHat(id: Int, name: String): @KittyHat {
        return <-create KittyHat(id: id, name: name)
    }

    access(all) resource Kitty {

        access(all) let id: Int

        // place where the Kitty hats are stored
        access(all) var items: @{String: KittyHat}

        init(newID: Int) {
            self.id = newID
            self.items <- {}
        }

        access(all) fun getKittyItems(): @{String: KittyHat} {
            var other: @{String:KittyHat} <- {}
            self.items <-> other
            return <- other
        }

        access(all) fun setKittyItems(items: @{String: KittyHat}) {
            var other <- items
            self.items <-> other
            destroy other
        }

        access(all) fun removeKittyItem(key: String): @KittyHat? {
            var removed <- self.items.remove(key: key)
            return <- removed
        }
    }

    access(all) fun createKitty(): @Kitty {
        return <-create Kitty(newID: 1)
    }
}

これらの定義は、Kittyリソースが帽子を所有できることを示しています。

帽子はKittyリソースの変数に格納されています。

    // place where the Kitty hats are stored
    access(all) var items: @{String: KittyHat}

キティの帽子を脱がせ、個別に移動させることができます。または、帽子を所有するキティを移動させ、帽子はキティと一緒に移動します。

KittyとKittyHatを作成し、Kittyに帽子を保存し、次にそれをアカウントのストレージに保存します。

import KittyVerse from 0x06

// This transaction creates a new kitty, creates two new hats and
// puts the hats on the cat. Then it stores the kitty in account storage.
transaction {
    prepare(acct: auth(SaveValue) &Account) {

        // Create the Kitty object
        let kitty <- KittyVerse.createKitty()

        // Create the KittyHat objects
        let hat1 <- KittyVerse.createHat(id: 1, name: "Cowboy Hat")
        let hat2 <- KittyVerse.createHat(id: 2, name: "Top Hat")

        let kittyItems <- kitty.getKittyItems()

        // Put the hat on the cat!
        let oldCowboyHat <- kittyItems["Cowboy Hat"] <- hat1
        destroy oldCowboyHat
        let oldTopHat <- kittyItems["Top Hat"] <- hat2
        destroy oldTopHat

        kitty.setKittyItems(items: <-kittyItems)

        log("The cat has the hats")

        // Store the Kitty in storage
        acct.storage.save(<-kitty, to: /storage/kitty)
    }
}

これで、キティとその帽子を一緒に移動させるトランザクションを実行し、キティからカウボーイハットを取り除き、キティに帽子を脱がせることができます。

import KittyVerse from 0x06

// This transaction moves a kitty out of storage, takes the cowboy hat off of the kitty,
// calls its tip hat function, and then moves it back into storage.
transaction {
    prepare(acct: auth(Storage) &Account) {

        // Move the Kitty out of storage, which also moves its hat along with it
        let kitty <- acct.storage.load<@KittyVerse.Kitty>(from: /storage/kitty)
            ?? panic("Kitty doesn't exist!")

        // Take the cowboy hat off the Kitty
        let cowboyHat <- kitty.removeKittyItem(key: "Cowboy Hat")
            ?? panic("cowboy hat doesn't exist!")

        // Tip the cowboy hat
        log(cowboyHat.tipHat())
        destroy cowboyHat

        // Tip the top hat that is on the Kitty
        log(kitty.items["Top Hat"]?.tipHat())

        // Move the Kitty to storage, which
        // also moves its hat along with it.
        acct.storage.save(<-kitty, to: /storage/kitty)
    }
}

このトランザクションを実行すると、次のような出力が表示されます。

> "Howdy Y'all"
> "Greetings, fellow aristocats!"

キティが動くと、その帽子も暗黙のうちに一緒に動きます。これは、帽子がキティの所有物であるためです。

Extensibility is coming

上記は、コンポーザブルリソースの簡単な例です。この例では、KittyがHatを所有できることを明示的に言わなければなりませんでした。しかし、Cadenceでは、所有リソースが所有可能性を最初から指定していなかった場合でも、開発者が分離したリソースが所有できるタイプを宣言できる、より強力なリソース拡張性を実現する方法が(補足: Cadence version1.0で)サポートされるようになりました。

この機能は「Attachment(アタッチメント)」と呼ばれ、この強力な機能について学ぶには、ドキュメントを確認してください!

Flow Playgroundで学んだことを実践してみましょう!

翻訳元->https://cadence-lang.org/docs/tutorial/resources-compose

Flow BlockchainのCadence version1.0ドキュメント (10. Composable Resources)

Previous << 9. Voting Contract

Next >> Language Reference

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?