Создаем на Flow | Изучаем FCL — 5 | Получите список NFT, хранящихся на определенном адресе
Published: 2022-07-01 14:58:34

## Краткий обзор
В этом руководстве вы расширите свои знания о взаимодействии с смарт-контрактами с помощью скриптов Cadence. Вы узнаете, как:

- извлекать список NFT, хранящихся на определенном адресе учетной записи (в этом примере мы будем использовать Flovatar!)
- получать и возвращать их в виде набора пользовательских структур

## Ранее в разделе "Изучение FCL"
В [предыдущем посте](https://dev.to/egormajj/sozdaiem-na-flow-izuchaiem-fcl-4-kak-prieobrazovat-find-identity-name-v-adries-4595) мы узнали, как можно взаимодействовать с развернутыми контрактами и как вернуть из скрипта пользовательское значение Struct. Опираясь на эти знания, мы выполним более сложную процедуру - получим список NFT, хранящихся на аккаунте, отобразим его в нужный нам формат, а затем вернем обратно.

Приступим! 💪

## Что такое Flovatar?

[Flovatar](https://flovatar.com/) - один из многих удивительных проектов NFT, построенных на Flow. Вместо того, чтобы покупать один из тысяч уникальных NFT, он предоставляет вам инструменты для создания собственной личности, соответствующей вашему стилю и предпочтениям! Вы сможете добавить свой личный стиль к окончательному персонажу Flovatar, которая будет соответствовать ВАШЕМУ стилю 😁.

## Подготовка
Прежде всего, необходимо найти адрес, где в настоящее время развернут контракт. На [GitHub Flovatar](https://github.com/crash13override/flovatar) на первой странице указаны адреса развернутых контрактов:

- Основная сеть — **0x921ea449dffec68a**
- Тестовая сеть — **0x0cf264811b95d465**

А в файле [get_flovatars.cdc](https://github.com/crash13override/flovatar/blob/main/scripts/get_flovatars.cdc) контракт Flovatar имеет удобный метод `getFlovatars`, принимающий в качестве аргумента адрес:

```javascript
import Flovatar from **0x921ea449dffec68a**
pub fun main(address:Address) : [Flovatar.FlovatarData] {
    return Flovatar.getFlovatars(address: address)
}
```

## Шаг 1 - Установка
Добавьте `"@onflow/fcl": "1.0.0"` в качестве зависимости

## Шаг 2 - Настройка
Как и в прошлый раз импортируем необходимые методы и настраиваем FCL:

```javascript
// Import methods from FCL
import { query, config } from "@onflow/fcl";

// Specify the API endpoint - Mainnet
const api = "https://rest-mainnet.onflow.org";

// Configure FCL to use testnet as the access node
config().put("accessNode.api", api);
```

## Шаг 3 - Реализация метода `getFlovatars`

```javascript
/// Get a List of Flovatars for Address
const getFlovatars = async (adddress) => {
    // inline code from above
    const cadence = `
        import Flovatar from **0x921ea449dffec68a**

        pub fun main(address:Address) : [Flovatar.FlovatarData] {
            return Flovatar.getFlovatars(address: address)
        }
    `

    // We need to pass single argument of type Address
    const args = (arg, t) => [arg(address, t.Address)];

    const flovatars = await query({ cadence, args });
    console.log({ flovatars })
}

```

## Шаг 4 - Попробуйте
Давайте сделаем запрос с помощью нашего метода. Нашей целью будет [Luca (создатель Flovatar)](https://find.xyz/luca) - его адрес `0x2a0eccae942667be`

```javascript
(async()=>{
    const user = "0x2a0eccae942667be"
    await getFlovatars(user)
})()
```
Если вы посмотрите в console.log, то увидите набор объектов, представляющих Flovatars:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3g276wi3lbza1tj0hwxw.png)
Не так уж и плохо, верно? Что ж... давайте попробуем развернуть это окно `metadata`:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zavpa166xkf73itqij9b.png)
Теперь это SVG для вас. Хотя вы можете извлекать эти данные каждый раз, когда пользователь обновляет страницу, в идеале вам нужно как-то кэшировать их и запрашивать только те данные, которые вам нужны.

Кроме того, если вы запросите учетную запись с сотнями/тысячами NFT, вы можете достигнуть предела возвращаемого значения, который составляет около ~10 Мбс.

Если вы зайдете на [Flovatar Showroom](https://flovatar.com/showroom) и воспользуетесь инструментами разработчика в вашем браузере, вы можете узнать, что все изображения кэшируются по адресу `https://flovatar.com/api/image/{id}`. Давайте извлечем только NFT `id` и `creatorAddress` в окне `metadata`. Так мы сможем определить, является ли владелец подлинным создателем данного NFT.

## Шаг 5 - Переписать скрипт Cadence
Как вы помните из прошлого поста, мы можем создать пользовательскую структуру, которая будет содержать все данные, которые мы хотим вернуть. Мы определим структуру `Avatar` с двумя полями: `id` и `isCreator`

```javascript
/// Get a List of Flovatars for Address
const getFlovatarsImproved = async (adddress) => {
    // inline code from above
    const cadence = `
        import Flovatar from **0x921ea449dffec68a

        pub struct Avatar{
      pub let id: UInt64
      pub let isCreator: Bool

      // underscore in front of the argument allows us to pass unnamed arguments
            init(_ id: UInt64, _ isCreator: Bool){
        self.id = id
        self.isCreator = isCreator
      }
        }**

        pub fun main(address:Address) : [Avatar] {
            // Just like last time we will call "getFlovatars" method
            let flovatars = Flovatar.getFlovatars(address: address)

      // We will collect processed Flovatar data here
      let data: [Avatar] = []

      // Below is a simple loop over Flovatars collected by the contract code
      for flovatar in flovatars {
        let isCreator = flovatar.metadata.creatorAddress == address
        let avatar = Avatar(flovatar.id, isCreator)

                // append newly created instance of Avatar into resulting array
        data.append(avatar)
      }
      return data  
    }
    `

    // We need to pass single argument of type Address
    const args = (arg, t) => [arg(address, t.Address)];

    const flovatars = await query({ cadence, args });
    console.log({ flovatars })
}
```

## Заключение

Давайте обновим наш IIFE и попробуем снова:

```javascript
(async ()=> {
    const user = "0x2a0eccae942667be"
    await getFlovatarsImproved(user)
})()
```
Такое обращение приведет к гораздо меньшей нагрузке:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1breag5zuqtghkt5isp2.png)
Содержащейся информации будет достаточно для создания ссылки `(https://flovatar.com/flovatars/{id})` или изображения `(https://flovatar.com/api/image/{id})` в вашем интерфейсе.

## ⭐ Дополнительное испытание
Используя знания из [поста .find identity resolver](https://dev.to/egormajj/sozdaiem-na-flow-izuchaiem-fcl-4-kak-prieobrazovat-find-identity-name-v-adries-4595), измените свой код, чтобы разрешить передачу .find identity в метод `getFlovatars`.

## Информационные ресурсы

- **Пример кода** - [https://codesandbox.io/s/dev-to-fcl-05-list-flovatars-at-address-0bibcd - full working solution](https://codesandbox.io/s/dev-to-fcl-05-list-flovatars-at-address-0bibcd - full working solution)
- **Cadence Structs** -[https://docs.onflow.org/cadence/language/composite-types/#composite-type-declaration-and-creation](https://docs.onflow.org/cadence/language/composite-types/#composite-type-declaration-and-creation)
- **Хранилище Flovatar GitHub** - [https://github.com/crash13override/flovatar](https://github.com/crash13override/flovatar)
- **Контракт Flovatar в источнике Flow View**  - [https://flow-view-source.com/mainnet/account/0x921ea449dffec68a/contract/Flovatar](https://flow-view-source.com/mainnet/account/0x921ea449dffec68a/contract/Flovatar)

Другие источники, которые могут быть вам полезны:

- **(ENG) | Документация Flow** - [https://docs.onflow.org/](https://docs.onflow.org/) - более детальная информации о блокчейне Flow и как взаимодействовать с ним
- **(ENG) | Flow Portal** - [https://flow.com/](https://flow.com/) - your entry point to Flow
- **(ENG) | FCL JS** - [https://github.com/onflow/fcl-js](https://github.com/onflow/fcl-js) - Исходный код и возможность поучаствовать в разработке библиотеки FCL JS library
- **(ENG) | Cadence** - [https://docs.onflow.org/cadence/](https://docs.onflow.org/cadence/) - Введение в язык программирования Cadence
- **Codesandbox** - [https://codesandbox.io](https://codesandbox.io) - Замечательная среда разработки и прототипирования прямо в вашем браузере