Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 22, 2022 01:44 am GMT

Build on Flow | Learn FCL - 9. How to pass Optional and Path Arguments to Scripts

Overview

Last time we covered how to pass arguments in scripts, weve intentionally omitted Optionals and Paths arguments to lower the mental load. Those 2 are still important and quite common, so we will cover them in this tutorial.

After you follow and complete example covered in this post you will be able to:

  • pass any Optional argument, regardless of its base type
  • pass Path arguments

But first, lets look at what they are!

Theory

Optionals are a bit like Schroedingers cat in programming: they can represent the presence or the absence of a value, when you check whats inside. Optionals have two cases:

  • there is a value
  • there is nil (nothing)

One use case where you might find this useful (that comes to my mind) is when you want to pass a Dictionary {String: String?} and want to initialize some of the fields with empty values (for whatever reason )

Paths arguments can be used when you want to use or access account storage in your script or transaction and doesnt want to hardcode that value, but rather make it more flexible.

Lets take a look at some common path /public/flowTokenVault - this is a path to the publicly available Capability to access the FLOW token Vault resource. With this specific Capability you can use it to get reference to that resource to read its balance or deposit more tokens into it. Not all Capabilities are equal though! Some might give your more functionality and others less.

Back to our capability. If you take a look at it you can see that it consists of two parts:

  • /public - this is called a domain.
  • /flowTokenVault - and this is an identifier

Technically / character is a separator, but I think its easier to see it this way

There are only three valid domains:storage,private, andpublic. In all of the scripts you will use public domain - since it wont allow you to access private and storage areas of other accounts.

Lets try to pass both of those into some scripts!

Step 1 - Installation

Add "@onflow/fcl": "1.0.0" as your dependency

Step 2 - Setup

Just like the last time we will import necessary methods and setup FCL:

// Import methods from FCLimport { query, config } from "@onflow/fcl";// Specify the API endpoint - this time we will use Mainnetconst api = "https://rest-mainnet.onflow.org";// Configure FCL to use mainnet as the access nodeconfig().put("accessNode.api", api);

Step 3 - Pass Path arguments

We will try to pass 3 different paths - PublicPath, PrivatePath and StoragePath - each one for respective domain:

// Path Argumentsconst 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 });};

Please, note that t.Path is a constant, even though we are passing object

Step 4 - Pass Optional Integer

To pass Optional, we need to wrap the type into t.Optional() call. And thats it

// Optionalsconst 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 });}; 

Step 5 - Pass Other Optional Types

In similar fashion to our original post about arguments lets pass other Optional types all at once:

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);};

Step 6 - Pass Optional Array and Array of Optionals

The difference between those two is in target for t.Optional() wrapper.

Heres 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 }); //};

And this one for optional array of 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 }); //};

Step 7 - Pass Dictionary with Optional values

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 });};

Have you noticed that script in last example returns Double Optional Int?? ? Thats because value at amount key might not exist, so it will return us Maybe(Maybe(Int)) - you will need to unwrap it twice if you want to use it later in the code

Finally

Let's add an IIFE at the end of the file and populate it with methods we have just defined:

(async () => {    console.clear();    // Path arguments  await passPathArgument();    // Optional arguments  await passOptionalIntegers();  await passMultiOptional();  await passArrayOfOptinalStrings();  await passOptionalArray();  await passDictionaryOfOptionals();})();

Some sparkling moments after you should see the output in the console log:

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

You did it - now those types are not a challenge to you!

Hope you find information in this post useful and will get back for more

Until next time!

Resources

Other resources you might find useful:


Original Link: https://dev.to/onflow/build-on-flow-learn-fcl-9-how-to-pass-optional-and-path-arguments-to-scripts-3cgn

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To