Создаем на Flow | Изучаем FCL — 9. Как передавать скриптам аргументы Options и аргументы Path

egormajj

EgorMajj

Posted on July 1, 2022

Создаем на Flow | Изучаем FCL — 9. Как передавать скриптам аргументы Options и аргументы Path

Краткий обзор

В прошлый раз, когда мы рассказывали о том, как передавать аргументы в скриптах, мы намеренно опустили аргументы Optionals и Paths, чтобы снизить умственную нагрузку. Эти два аргумента по-прежнему важны и довольно часто встречаются, поэтому мы рассмотрим их в этом уроке.

После того, как вы выполните все примеры, описанные в этом посте, вы сможете:

  • передавать любой аргумент Optional, независимо от его базового типа
  • передавать Path аргументы

Но сначала давайте посмотрим, что это такое!

Теория

Optionals - это что-то вроде кота Schroedinger в программировании: они могут представлять наличие или отсутствие значения, когда вы проверяете, что находится внутри. У опций есть два случая:

есть значение
есть nil (ничего).

Один из примеров использования, где вы можете найти это полезным (который приходит мне на ум) - это когда вы хотите передать Dictionary {String: String?} и хотите инициализировать некоторые строки пустыми значениями (по какой-либо причине 🤷♂️).

Paths Аргументы могут быть использованы, когда вы хотите использовать или получить доступ к хранилищу учетных записей в своем скрипте или транзакции и не хотите жестко кодировать это значение, а хотите сделать его более гибким.

Рассмотрим некоторые распространенные Path /public/flowTokenVault - это path к управлению доступом ресурса FLOW token Vault. С помощью этой специфической способности вы можете получить ссылку на этот ресурс, чтобы посмотреть его баланс или пополнить его токенами. Однако не все возможности одинаковы! Некоторые могут дать вам больше функциональности, а другие - меньше.

Вернемся к нашей функции. Если вы посмотрите на нее, то увидите, что она состоит из двух частей:

  • /public - это называется domain.
  • /flowTokenVault - а это идентификатор.

Технически символ / является разделителем, но я думаю, что проще увидеть это так 😉.

Существует только три допустимых domain: storage, private и public. Во всех скриптах вы будете использовать public domain - поскольку он не позволит вам получить доступ к private областям и областям storage других учетных записей.

Давайте попробуем передать оба этих domain в некоторых скриптах! 💪

Шаг 1 - Установка

Добавьте "@onflow/fcl": "1.0.0" в качестве зависимости

Шаг 2 - Настройка

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

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

// Specify the API endpoint - this time we will use Mainnet
const api = "https://rest-mainnet.onflow.org";

// Configure FCL to use mainnet as the access node
config().put("accessNode.api", api);
Enter fullscreen mode Exit fullscreen mode

Шаг 3 - Передача Path аргументов

Мы попытаемся передать 3 различных Path - PublicPath, PrivatePath и StoragePath - каждый для соответствующего domain:

// Path Arguments
const passPathArgument = async () => {
  const cadence = `
    pub fun main(public: PublicPath, private: PrivatePath, storage: StoragePath): PrivatePath{
      // we can return any value, but let's return one of the Paths to see
      // how FCL decodes it into value
      return private
    }
  `;

  // Since we are not gonna use any of those for actual data access
  // we can construct any paths we like
  // this one will encode "/public/flowTokenVault"
  const publicPath = {
    domain: "public",
    identifier: "flowTokenVault"
  };

  // encode "/private/flowTokenVault"
  const privatePath = {
    domain: "private",
    identifier: "flowTokenVault"
  };

  // encode "/storage/flowTokenVault"
  const storagePath = {
    domain: "storage",
    identifier: "flowTokenVault"
  };

  // Notice that t.Path is not a function, but a constant!
  const args = (arg, t) => [
    arg(publicPath, t.Path),
    arg(privatePath, t.Path),
    arg(storagePath, t.Path)
  ];
  const result = await query({ cadence, args });
  console.log({ result });
};
Enter fullscreen mode Exit fullscreen mode

Обратите внимание, что t.Path является постоянным, несмотря на то, что мы передаем объект 🤪.

Шаг 4 - Передача Optional целому числу

Чтобы передать Optional, нам нужно обернуть тип в вызов t.Optional(). Вот и все 😊.

// Optionals
const passOptionalIntegers = async () => {
  const cadence = `
    pub fun main(a: Int?): Int?{
      return a
    }
  `;

  // We will set value of our Int argument to null to check that script works correctly
  const a = null;
  const args = (arg, t) => [arg(a, t.Optional(t.Int))];

  const result = await query({ cadence, args });
  console.log({ result });
}; 
Enter fullscreen mode Exit fullscreen mode

Шаг 5 - Pass других Optional типов

По аналогии с нашей первоначальной статьей об аргументах, давайте передадим другие типы Optional все сразу:

const passMultiOptional = async () => {
  const cadence = `
    pub fun main(a: String?, b: Bool?, c: UFix64?, d: Address?): Address?{
      return d
    }
  `;

    // it's perfectly fine to pass non-nil values alongside "empty"
  const a = "Hello";
  const b = null;
  const c = null;
  const d = "0x01";

  // Note the types are the same as we specify in Cadence code
  const args = (arg, t) => [
    arg(a, t.Optional(t.String)),
    arg(b, t.Optional(t.Bool)),
    arg(c, t.Optional(t.UFix64)),
    arg(d, t.Optional(t.Address))
  ];

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

  showResult("multiple", result);
};
Enter fullscreen mode Exit fullscreen mode

Шаг 6 - Pass Optional Array и Array of Optionals

Разница между ними заключается в цели для обертки t.Optional().

Вот array of Optionals:

const passArrayOfOptinalStrings = async () => {
  const cadence = `
    pub fun main(a: [String?]): String?{
      return a[0]
    }
  `;

  const a = ["Hello", null];
  // Type of the argument is composed of t.Array, t.Optional and t.String
  const args = (arg, t) => [arg(a, t.Array(t.Optional(t.String)))];
  const result = await query({ cadence, args });
  console.log({ result }); //
};
Enter fullscreen mode Exit fullscreen mode

А этот для опционального массива Strings:

const passOptionalArray = async () => {
  const cadence = `
    pub fun main(a: [String]?): String?{
      if let arr = a {
        return arr[0]
      }

      return nil
    }
  `;
  const a = null;
  // This time we will wrap our array in "t.Optional()" call
  const args = (arg, t) => [arg(a, t.Optional(t.Array(t.String)))];
  const optionalArray = await query({ cadence, args });
  console.log({ optionalArray }); //
};
Enter fullscreen mode Exit fullscreen mode

Шаг 7 - Передача Dictionary с Optional значениями

const passDictionaryOfOptionals = async () => {
  // In this example we will pass a Cadence Dictionary as argument
  // keys will be of type "String" and values will be Optionals of type "Int?"
  const cadence = `
    pub fun main(a: {String: Int?}): Int??{
      return a["amount"]
    }
  `;

  // Dictionaries should be represented as array of key/value pairs of respective types
  // Note that we shall pass numeric value as string here
  const a = [{ key: "amount", value: "42" }];
  // Dictionary type is composed out of t.Dictionary, t.String and t.Int for our case
  const args = (arg, t) => [
    arg(a, t.Dictionary({ key: t.String, value: t.Optional(t.Int) }))
  ];

  const result = await query({ cadence, args });
  console.log({ result });
};
Enter fullscreen mode Exit fullscreen mode

💡 Вы заметили, что скрипт в последнем примере возвращает Double Optional Int(?). ? Это потому, что значение по ключу amount может не существовать, поэтому он вернет нам Maybe(Maybe(Int)) - вам нужно будет развернуть его дважды, если вы хотите использовать его позже в коде 😉

Заключение

Давайте добавим IIFE в конец файла и заполним его методами, которые мы только что определили:

(async () => {
    console.clear();

    // Path arguments
  await passPathArgument();

    // Optional arguments
  await passOptionalIntegers();
  await passMultiOptional();
  await passArrayOfOptinalStrings();
  await passOptionalArray();
  await passDictionaryOfOptionals();
})();
Enter fullscreen mode Exit fullscreen mode

Через несколько 🎇 мгновений после этого вы должны увидеть вывод в журнале консоли:

{result: Object}
    result: {
        domain: "private",
        identifier: "flowTokenVault"
    }
{result: null}
{result: "0x0000000000000001"}
{result: "Hello"}
{optionalArray: null}
{result: "42"}
Enter fullscreen mode Exit fullscreen mode

Вы сделали это - теперь эти типы не являются для вас испытанием! 💪

Надеюсь, информация в этом посте будет полезной, и вы вернетесь за новыми материалами 😉.

До следующего раза! 👋

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

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

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

Posted on July 1, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

What was your win this week?
weeklyretro What was your win this week?

November 29, 2024

Where GitOps Meets ClickOps
devops Where GitOps Meets ClickOps

November 29, 2024

How to Use KitOps with MLflow
beginners How to Use KitOps with MLflow

November 29, 2024

Modern C++ for LeetCode 🧑‍💻🚀
leetcode Modern C++ for LeetCode 🧑‍💻🚀

November 29, 2024