Overview
Final time we lined how one can cross arguments in scripts, we’ve deliberately omitted Optionals and Paths arguments to decrease the psychological load. These 2 are nonetheless essential and fairly frequent, so we’ll cowl them on this tutorial.
After you observe and full instance lined on this publish it is possible for you to to:
- cross any Elective argument, no matter its base kind
- cross Path arguments
However first, let’s have a look at what they’re!
Concept
Optionals
are a bit like Schroedinger’s cat in programming: they will characterize the presence or the absence of a worth, whenever you verify what’s inside. Optionals have two circumstances:
- there’s a worth
- there may be
nil
(nothing)
One use case the place you would possibly discover this convenient (that involves my thoughts) is whenever you need to cross a Dictionary {String: String?}
and need to initialize a number of the fields with empty values (for no matter purpose 🤷♂️)
Paths
arguments can be utilized whenever you need to use or entry account storage in your script or transaction and doesn’t need to hardcode that worth, however reasonably make it extra versatile.
Let’s check out some frequent path /public/flowTokenVault
– it is a path to the publicly obtainable Functionality to entry the FLOW token Vault useful resource. With this particular Functionality you should use it to get reference to that useful resource to learn it’s stability or deposit extra tokens into it. Not all Capabilities are equal although! Some would possibly give your extra performance and others much less.
Again to {our capability}. Should you check out it you possibly can see that it consists of two elements:
-
/public – that is referred to as a
area
. - /flowTokenVault – and that is an identifier
Technically /
character is a separator, however I feel it’s simpler to see it this manner 😉
There are solely three legitimate domains: storage
, personal
, and public
. In all the scripts you’ll use public
area – because it received’t permit you to entry personal
and storage
areas of different accounts.
Let’s attempt to cross each of these into some scripts! 💪
Step 1 – Set up
Add "@onflow/fcl": "1.0.0"
as your dependency
Step 2 – Setup
Similar to the final time we’ll import vital strategies and setup FCL:
// Import strategies from FCL
import { question, config } from "@onflow/fcl";
// Specify the API endpoint - this time we'll use Mainnet
const api = "https://rest-mainnet.onflow.org";
// Configure FCL to make use of mainnet because the entry node
config().put("accessNode.api", api);
Step 3 – Cross Path arguments
We are going to attempt to cross 3 totally different paths – PublicPath
, PrivatePath
and StoragePath
– each for respective area:
// Path Arguments
const passPathArgument = async () => {
const cadence = `
pub enjoyable principal(public: PublicPath, personal: PrivatePath, storage: StoragePath): PrivatePath{
// we will return any worth, however let's return one of many Paths to see
// how FCL decodes it into worth
return personal
}
`;
// Since we aren't gonna use any of these for precise information entry
// we will assemble any paths we like
// this one will encode "/public/flowTokenVault"
const publicPath = {
area: "public",
identifier: "flowTokenVault"
};
// encode "/personal/flowTokenVault"
const privatePath = {
area: "personal",
identifier: "flowTokenVault"
};
// encode "/storage/flowTokenVault"
const storagePath = {
area: "storage",
identifier: "flowTokenVault"
};
// Discover that t.Path shouldn't be a perform, however a relentless!
const args = (arg, t) => [
arg(publicPath, t.Path),
arg(privatePath, t.Path),
arg(storagePath, t.Path)
];
const outcome = await question({ cadence, args });
console.log({ outcome });
};
Please, be aware that t.Path
is a continuing, although we’re passing object 🤪
Step 4 – Cross Elective Integer
To cross Elective, we have to wrap the kind into t.Elective()
name. And that’s it 😊
// Optionals
const passOptionalIntegers = async () => {
const cadence = `
pub enjoyable principal(a: Int?): Int?{
return a
}
`;
// We are going to set worth of our Int argument to null to verify that script works appropriately
const a = null;
const args = (arg, t) => [arg(a, t.Optional(t.Int))];
const outcome = await question({ cadence, args });
console.log({ outcome });
};
Step 5 – Cross Different Elective Varieties
In comparable vogue to our unique publish about arguments let’s cross different Elective sorts unexpectedly:
const passMultiOptional = async () => {
const cadence = `
pub enjoyable principal(a: String?, b: Bool?, c: UFix64?, d: Deal with?): Deal with?{
return d
}
`;
// it is completely wonderful to cross non-nil values alongside "empty"
const a = "Whats up";
const b = null;
const c = null;
const d = "0x01";
// Be aware the categories are the identical 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 outcome = await question({ cadence, args });
console.log({ outcome });
showResult("a number of", outcome);
};
Step 6 – Cross Elective Array and Array of Optionals
The distinction between these two is in goal for t.Elective()
wrapper.
Right here’s array of Optionals:
const passArrayOfOptinalStrings = async () => {
const cadence = `
pub enjoyable principal(a: [String?]): String?{
return a[0]
}
`;
const a = ["Hello", null];
// Kind of the argument consists of t.Array, t.Elective and t.String
const args = (arg, t) => [arg(a, t.Array(t.Optional(t.String)))];
const outcome = await question({ cadence, args });
console.log({ outcome }); //
};
And this one for elective array of Strings:
const passOptionalArray = async () => {
const cadence = `
pub enjoyable principal(a: [String]?): String?{
if let arr = a {
return arr[0]
}
return nil
}
`;
const a = null;
// This time we'll wrap our array in "t.Elective()" name
const args = (arg, t) => [arg(a, t.Optional(t.Array(t.String)))];
const optionalArray = await question({ cadence, args });
console.log({ optionalArray }); //
};
Step 7 – Cross Dictionary with Elective values
const passDictionaryOfOptionals = async () => {
// On this instance we'll cross a Cadence Dictionary as argument
// keys might be of kind "String" and values might be Optionals of kind "Int?"
const cadence = `
pub enjoyable principal(a: {String: Int?}): Int??{
return a["amount"]
}
`;
// Dictionaries ought to be represented as array of key/worth pairs of respective sorts
// Be aware that we will cross numeric worth as string right here
const a = [{ key: "amount", value: "42" }];
// Dictionary kind consists 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 outcome = await question({ cadence, args });
console.log({ outcome });
};
💡 Have you ever observed that script in final instance returns Double Elective
Int??
? That’s as a result of worth atquantity
key won’t exist, so it should return usPossibly(Possibly(Int))
– you will want to unwrap it twice if you wish to use it later within the code 😉
Lastly
Let’s add an IIFE on the finish of the file and populate it with strategies we’ve got simply outlined:
(async () => {
console.clear();
// Path arguments
await passPathArgument();
// Elective arguments
await passOptionalIntegers();
await passMultiOptional();
await passArrayOfOptinalStrings();
await passOptionalArray();
await passDictionaryOfOptionals();
})();
Some glowing 🎇 moments after it’s best to see the output within the console log:
{outcome: Object}
outcome: {
area: "personal",
identifier: "flowTokenVault"
}
{outcome: null}
{outcome: "0x0000000000000001"}
{outcome: "Whats up"}
{optionalArray: null}
{outcome: "42"}
You probably did it – now these sorts aren’t a problem to you! 💪
Hope you discover info on this publish helpful and can get again for extra 😉
Till subsequent time! 👋
Assets
Different assets you would possibly discover helpful: