7. Marketplace Setup

[Previous << 6. Fungible Token Tutorial](https://qiita.com/flowcadence/items/d4f98c76d5f88d447345)
[Next >> 8. Marketplace](https://qiita.com/flowcadence/items/4ccd756d0a2a71c6059b)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#cadenceの言語仕様を学ぶ

このチュートリアルでは、以前のチュートリアルで学んだ可換トークン（FT）と非可換トークン（NFT）の両方のスマートコントラクトを使用するマーケットプレイスを作成します。このページでは、マーケットプレイス・チュートリアルを完了するために、アカウントをセットアップするための一連のトランザクションを実行する必要があります。次のページには、チュートリアルの主な内容が記載されています。

チュートリアルを終えたら、[NFTStorefrontリポジトリ](https://github.com/onflow/nft-storefront)をチェックして、テストネットまたはメインネットですぐに利用できる、本番稼働可能なマーケットプレイスの例を確認してください。

:::note
ⓘ Action
このチュートリアルのスターターコードをFlow Playgroundで開きます：
https://play.flow.com/7355d51c-066b-46be-adab-a3da6c28b645
このチュートリアルでは、このコードと対話するためにさまざまな操作を行うよう求められます。
:::
Marketplace チュートリアルをすでに完了している場合は、[Composable Resources: Kitty Hats](https://qiita.com/flowcadence/items/729d4317f64df7882783) に進んでください。

このガイドでは、Marketplace チュートリアルを完了するために必要な状態にプレイグラウンドを素早く設定する方法を説明します。Marketplace チュートリアルでは、fungible トークンと non-fungible トークンスマートコントラクトを使用して、fungible トークンで NFT を購入および販売できるようにします。

:::note
ⓘ Action
これらのセットアップ手順のコードの一部には、意図的にエラーが組み込まれています。Cadenceについて十分に理解し、これらのチュートリアルを自力で修正できる必要があります。すべてのエラーは、以前のチュートリアルで学んだ概念に関連しています
:::
1. `ExampleToken` コントラクトを開きます。これはfungible tokenチュートリアルと同じコントラクトです。
2. `ExampleToken` コードをアカウント`0x06`にデプロイします。
3. `ExampleNFT` コントラクト（Contract 2）に切り替えます
4. NFTコードをデプロイする署名者として選択し、アカウント`0x07`にデプロイします。
5. 「Setup 6」でトランザクションを実行します。これは`SetupAccount6Transaction.cdc`ファイルです。アカウント`0x06`のストレージをセットアップする唯一の署名者として、アカウント`0x06`を使用します。

```ruby:SetupAccount6Transaction.cdc
/* SetupAccount6Transaction.cdc */

import ExampleToken from 0x06
import ExampleNFT from 0x07

/* This transaction sets up account 0x06 for the marketplace tutorial
   by publishing a Vault reference and creating an empty NFT Collection. */
transaction {
  prepare(acct: auth(SaveValue) &Account) {
    /* Create a public Receiver capability to the Vault */
    let receiverCap = acct.capabilities.storage.issue<&{ExampleToken.Receiver}>(
        /storage/CadenceFungibleTokenTutorialVault
    )
    acct.capabilities.publish(receiverCap, at: /public/CadenceFungibleTokenTutorialReceiver)

    /* store the empty NFT Collection in account storage */
    acct.storage.save(<-ExampleNFT.createEmptyCollection(nftType: nil), to: ExampleNFT.CollectionStoragePath)

    log("Collection created for account 2")

    /* create a public capability for the Collection */
    let cap = acct.capabilities.storage.issue<&ExampleNFT.Collection>(ExampleNFT.CollectionStoragePath)
    acct.capabilities.publish(cap, at: ExampleNFT.CollectionStoragePath)
  }
}
```

7 . 2つ目のトランザクション「Setup 7」を実行します。これは`SetupAccount7Transaction.cdc`ファイルです。アカウント`0x07`の唯一の署名者として、アカウント`0x07`のストレージを設定します。
```ruby:SetupAccount7Transaction.cdc
/* SetupAccount7Transaction.cdc */

import ExampleToken from 0x06
import ExampleNFT from 0x07

/* This transaction adds an empty Vault to account 0x07
   and mints an NFT with id=1 that is deposited into
   the NFT collection on account 0x06. */
transaction {

  /* Private reference to this account's minter resource */
  let minterRef: &ExampleNFT.NFTMinter

  prepare(acct: auth(BorrowValue, SaveValue, StorageCapabilities, PublishCapability) &Account) {
    /* create a new vault instance */
    let vaultA <- ExampleToken.createEmptyVault()

    /* Store the vault in the account storage */
    acct.storage.save(<-vaultA, to: ExampleToken.VaultStoragePath)

    /* Create a public Receiver capability to the Vault */
    let receiverCap = acct.capabilities.storage.issue<&ExampleToken.Vault>(
        ExampleToken.VaultStoragePath
    )
    acct.capabilities.publish(receiverCap, at: ExampleToken.VaultPublicPath)
  }
  execute {
    /* Get the recipient's public account object */
    let recipient = getAccount(0x06)

    /* Get the Collection reference for the receiver
       getting the public capability and borrowing a reference from it */
    let receiverRef = recipient.capabilities
        .borrow<&ExampleNFT.Collection>(ExampleNFT.CollectionPublicPath)
        ?? panic("Could not borrow a collection reference to 0x06's ExampleNFT.Collection"
                 .concat(" from the path ")
                 .concat(ExampleNFT.CollectionPublicPath.toString())
                 .concat(". Make sure account 0x06 has set up its account ")
                 .concat("with an ExampleNFT Collection."))

    /* Mint an NFT and deposit it into account 0x06's collection */
    receiverRef.deposit(token: <-ExampleNFT.mintNFT())
  }
}
```
8 . 「Setup 6」でトランザクションを実行します。これは`SetupAccount6TransactionMinting.cdc`ファイルです。アカウント`0x06`を唯一の署名者として使用し、アカウント6と7のfungibleトークンを発行します。

```ruby:SetupAccount6TransactionMinting.cdc
/* SetupAccount6TransactionMinting.cdc */

import ExampleToken from 0x06
import ExampleNFT from 0x07

/* This transaction mints tokens for both accounts using
   the minter stored on account 0x06. */
transaction {

  /* Public Vault Receiver References for both accounts */
  let acct6Capability: Capability<&{ExampleToken.Receiver}>
  let acct7Capability: Capability<&{ExampleToken.Receiver}>

  /* Private minter references for this account to mint tokens */
  let minterRef: &ExampleToken.VaultMinter

  prepare(acct: auth(SaveValue, StorageCapabilities, BorrowValue) &Account) {
    /* Get the public object for account 0x07 */
    let account7 = getAccount(0x07)

    /* Retrieve public Vault Receiver references for both accounts */
    self.acct6Capability = acct.capabilities.get<&{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)
    self.acct7Capability = account7.capabilities.get<&{ExampleToken.Receiver}>(/public/CadenceFungibleTokenTutorialReceiver)

    /* Get the stored Minter reference for account 0x06 */
    self.minterRef = acct.storage.borrow<&ExampleToken.VaultMinter>(from: /storage/CadenceFungibleTokenTutorialMinter)
        ?? panic("Could not borrow owner's vault minter reference")
  }

  execute {
    /* Mint tokens for both accounts */
    self.minterRef.mintTokens(amount: 20.0, recipient: self.acct7Capability)
    self.minterRef.mintTokens(amount: 10.0, recipient: self.acct6Capability)
  }
}
```

9 . Script1にある`CheckSetupScript.cdc`ファイルを実行して、すべてのセットアップが完了していることを確認します。
```ruby:CheckSetupScript.cdc
/* CheckSetupScript.cdc */

import ExampleToken from 0x06
import ExampleNFT from 0x07

/** Allows the script to return the ownership info
    of all the accounts */
access(all) struct OwnerInfo {
  access(all) let acct6Balance: UFix64
  access(all) let acct7Balance: UFix64

  access(all) let acct6IDs: [UInt64]
  access(all) let acct7IDs: [UInt64]

  init(balance1: UFix64, balance2: UFix64, acct6IDs: [UInt64], acct7IDs: [UInt64]) {
    self.acct6Balance = balance1
    self.acct7Balance = balance2
    self.acct6IDs = acct6IDs
    self.acct7IDs = acct7IDs
  }
}

/* This script checks that the accounts are set up correctly for the marketplace tutorial.
  
   Account 0x06: Vault Balance = 40, NFT.id = 1
   Account 0x07: Vault Balance = 20, No NFTs */
access(all) fun main(): OwnerInfo {
    /* Get the accounts' public account objects */
    let acct6 = getAccount(0x06)
    let acct7 = getAccount(0x07)

    /* Get references to the account's receivers
       by getting their public capability
       and borrowing a reference from the capability */
    let acct6ReceiverRef = acct6.capabilities.get<&{ExampleToken.Balance}>
                          (/public/CadenceFungibleTokenTutorialReceiver)
                          .borrow()
            ?? panic("Could not borrow a balance reference to "
                     .concat("0x06's ExampleToken.Vault")
                     .concat(". Make sure 0x06 has set up its account ")
                     .concat("with an ExampleToken Vault and valid capability."))

    let acct7ReceiverRef = acct7.capabilities.get<&{ExampleToken.Balance}>
                          (/public/CadenceFungibleTokenTutorialReceiver)
                          .borrow()
            ?? panic("Could not borrow a balance reference to "
                     .concat("0x07's ExampleToken.Vault")
                     .concat(". Make sure 0x07 has set up its account ")
                     .concat("with an ExampleToken Vault and valid capability."))

    let returnArray: [UFix64] = []

    /* verify that the balances are correct */
    if acct6ReceiverRef.balance != 40.0 || acct7ReceiverRef.balance != 20.0 {
        panic("Wrong balances!")
    }

    /* Find the public Receiver capability for their Collections */
    let acct6Capability = acct6.capabilities.get<&{ExampleNFT.NFTReceiver}>(ExampleNFT.CollectionPublicPath)
    let acct7Capability = acct7.capabilities.get<&{ExampleNFT.NFTReceiver}>(ExampleNFT.CollectionPublicPath)

    /* borrow references from the capabilities */
    let nft1Ref = acct6Capability.borrow()
        ?? panic("Could not borrow a collection reference to 0x06's ExampleNFT.Collection"
                 .concat(" from the path ")
                 .concat(ExampleNFT.CollectionPublicPath.toString())
                 .concat(". Make sure account 0x06 has set up its account ")
                 .concat("with an ExampleNFT Collection."))

    let nft2Ref = acct7Capability.borrow()
        ?? panic("Could not borrow a collection reference to 0x07's ExampleNFT.Collection"
                 .concat(" from the path ")
                 .concat(ExampleNFT.CollectionPublicPath.toString())
                 .concat(". Make sure account 0x07 has set up its account ")
                 .concat("with an ExampleNFT Collection."))

    /* verify that the collections are correct */
    if nft1Ref.getIDs()[0] != 1 || nft2Ref.getIDs().length != 0 {
        panic("Wrong Collections!")
    }

    /* Return the struct that shows the account ownership info */
    return OwnerInfo(balance1: acct6ReceiverRef.balance,
                     balance2: acct7ReceiverRef.balance,
                     acct6IDs: nft1Ref.getIDs(),
                     acct7IDs: nft2Ref.getIDs())
}
```
10 . Scriptがpanicを起こすことはなく、次のような出力が表示されるはずです。
```
"Account 6 Balance"
40.00000000
"Account 7 Balance"
20.00000000
"Account 6 NFTs"
[1]
"Account 7 NFTs"
[]
```
これでプレイグラウンドが正しい状態になりましたので、次のチュートリアルに進むことができます。

マーケットプレイスのチュートリアルでは、新しいプレイグラウンドセッションを開く必要はありません。このまま続けてください。

翻訳元

https://cadence-lang.org/docs/tutorial/marketplace-setup

***
<b>[Previous << 6. Fungible Token Tutorial](https://qiita.com/flowcadence/items/d4f98c76d5f88d447345)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (7. Marketplace Setup)

<b>[Next >> 8. Marketplace](https://qiita.com/flowcadence/items/4ccd756d0a2a71c6059b)</b>