Deploy and Interact with Serverless Functions using EXM CLI

Community Labs
5 min readJan 12, 2023

--

Written by Rohit Pathare

Execution Machine (EXM) is a developer platform that provides the ability to create and leverage blockchain-based (permanent) serverless functions without the need for knowledge of or access to blockchain technologies like wallets and tokens.

In an earlier article we understood how Execution Machine and its supporting technologies work.

In this article we will walkthrough a basic code example for deploying and interacting with serverless functions using EXM’s CLI.

Want to use EXM in an application instead? Checkout the article on using the EXM JavaScript SDK.

Initial Setup

In order to use the EXM CLI we must globally install the package on our device:

npm install -g @execution-machine/cli

Upon installation we can run exm help in the command line to see the list of available commands.

In general, the format for interacting with functions is exm function:* where the * will be replaced with specific interaction sub commands like deploy, write, read, etc.

Defining the Function

To begin working with the CLI, we either need a function source that must first be deployed on Arweave or the function id of an already deployed function.

Let’s start by creating a function from scratch. In a new file named function.js we stored the following logic:

export function handle(state, action) {
state.users.push(action.input.name);
return { state }
}

The syntax for defining functions is based off of the standard implemented by SmartWeave for smart contracts on Arweave in JavaScript language. Every function has a state which is a JSON object of values stored in it and actions to interact with these values. The values can either be some variables or a ledger of action calls that have updated these variables.

The purpose of the function above is to store names in an array which is done with the following line:

state.users.push(action.input.name);

When deploying our function an empty array named users is initialised inside the state that later helps our function to identify this state variable (variable stored in state of the function) during read and write calls. Upon deployment the state will look like this:

{ users: [] }

Additionally, while writing to the function, we will use the key named name to help the function identify the value passed in to the write operation. Both these naming definitions gain further significance when dealing with multiple values.

EXM API Token

In order to use most of EXM’s features we need a Token or Key which can be created here.

⚠️ The API_TOKEN is an identifier to our account and lets us access functions associated with it. Hence, it is vital to ensure this token is kept secret to prevent any spams and attacks to our functions.

Deploying the Serverless Function

Once we have the function and the API Token, we can deploy the function. Make sure you are in the directory that houses the function.js file when running this command or pass in the appropriate relative file path.

exm function:deploy --src function.js --init-state '{ "users": [] }' --token EXM_API_TOKEN

We must pass in some flags with the deploy command as helpers to tell EXM how we want to execute the command. The syntax for using any flag in general is --flag-name value.

  • --src tells the EXM CLI which file it must use for the function logic. It is the absolute or relative path to the file.
  • --init-state defines the initial state for the function. The format for init state value must be a valid JSON string as follows:
--init-state '{ "variable1": initial value1, "variable2": initial value2 }'
  • --init-state-src (optional) can be used instead of --init-state if the function’s state needs to handle too many variables. A separate json file with the following format should be passed to this flag:
'{
"variable1": initial value1,
"variable2": initial value2,
"variable3": initial value3,
}'
  • --token is the EXM API Token fetched earlier which helps EXM associate the function with the Token. Ensure the safety of this token by keeping it private.

A prompt seeking confirmation appears.

Do you want to deploy this function? Yes

On successful deployment, a unique function id is received which helps identify the function. Make sure to save this for further interactions like read and write operations.

cV8U3DYvX4hJRts0AtQpoiYLPYvjdSLEWoYtw6nKUqA

Writing to the Function

Once the function is deployed, we can interact with it by writing a value to the users array.

To do so, we use the following command:

exm function:write <function id> --input '{ "name": "Open Sourcerer" }' --token EXM_API_TOKEN

The function id received when deploying must be passed in to identify the function we want to write to.

Additionally, a few other flags are available to further define the interaction:

  • --input is the value to be passed to the function.
  • --tags (optional) to be passed to the function to help easily index and query the interactions for future reference. To pass tags, the following format is needed:
--tags name1=value1 --tags name2=value2
  • --show-output (optional) returns the updated state upon successful execution of the write operation.
  • --token is the EXM API Token.

Reading from the Function

Now that we have a value stored in our array, let’s try reading it. To read the state of a function, we simply run the following:

exm function:read <function id>

For reading from a function, we only need to pass in the function id.

This returns the current state of the function.

{
"users": [
"Open Sourcerer"
]
}

Lazy Evaluating from Arweave

There is another way to read the state of a function with the help of something known as lazy evaluation.

Previously, on using the read command, the values returned were fetched from EXM’s cached layer.

On the other hand, lazy evaluation reads the data directly from Arweave. As the functions itself and any interactions (write operations) with them are stored on chain, they can be accessed by any user and evaluated to check the current state of a function. This is ideal when verification is needed to check if the state stored on EXM’s cached layer matches the state stored on chain.

However, there is a delay involved between the submission of an interaction request and it being processed on chain and the state being updated. This is where EXM comes in. It provides us immediate access to the updated state by storing a copy of the function on a cached layer while the state of the function is updated on chain in the background.

For a better understanding of lazy evaluation, checkout the article explaining how EXM works.

We can lazy evaluate a function with another simple command:

exm function:evaluate <functionId>

Again, we only need to pass in the function id for this.

A Quick Recap

The process starts off by installing the EXM CLI package on the device. Then we define the function logic and fetch the API Token. With both setup, we deploy the function, write to it and read from it. Finally, we get a basic understanding of lazy evaluation and when this might be useful over the read command.

Great job, now you’re armed with the basic understanding of how the EXM CLI works!

To learn more about EXM read their docs. For any help join the Discord and make sure to share your projects with us on Twitter.

Fin.

--

--

Community Labs

Community Labs is a software development company and venture studio focused on the Arweave ecosystem.