Getting Started with Blockless Functions: Manifest and Extension

Blockless
6 min readApr 20, 2023

Mastering Blockless Manifest and Extensions: Unlock the Full Potential of Decentralized Serverless Applications

In this article, we dive into configuring your Function Manifest for Blockless. We will discuss how to create a sample bls.toml file, and explore the different configuration sections including top-level, deployment, and build configurations.

Additionally, we will cover Blockless Extensions, which offer a way to enhance your project’s capabilities through internal, external, or CGI-based extensions. By understanding the essentials of Blockless configuration and extensions, you will be able to unlock the full potential of the platform for your decentralized applications.

Configure Your Function Manifest

Blockless utilizes a configuration file called bls.toml to enable customization of the development and publishing setup for your Blockless Function.

Here, you can find a sample bls.toml file that is generated when you run the bls function init command to create a new Hello World project.

name = "yodelling-coffee-pony"
type = "function"
version = "1.0.0"
content_type = "json"

[deployment]
nodes = 4
permissions = [
"<https://bsc-dataseed.binance.org>",
"<https://api.coingecko.com>",
"<https://redis-domain>:port"
]

[build]
dir = "build"
entry = "yodelling-coffee-pony_debug.wasm"
command = "npm run build:debug"

[build_release]
dir = "build"
entry = "yodelling-coffee-pony.wasm"
command = "npm run build:release"

Top-Level Configuration

In the top-level configuration, you can define your function’s name and version.

name = "yodelling-coffee-pony"
type = "function"
version = "1.0.0"
content_type = "json"

name string Required

The name property is a string that represents the unique identifier for your function.

version string Optional

The version property is an optional string that represents the version of your function.

type string Optional

The type property is an optional string that determines the type of deployment. Currently, the type field can be either "function" or "site". If not provided, it defaults to "function".

content_type string Optional

The content_type property is an optional string that defines the content type for the response returned by your function or site. Some type examples are: "json", "html", or "text". If not provided, it defaults to "text".

Deployment Configuration

The deployment section is used to specify the deployment settings for the application.

[deployment]
nodes = 4
permissions = [
"<https://bsc-dataseed.binance.org>",
"<https://api.coingecko.com>",
"<https://redis-domain>:port"
]

nodes integer Optional

The nodes property is an optional integer that represents the number of nodes to be deployed for your function or site. If not provided, it defaults to 1.

permissions array of strings Conditional

The permissions property is an array of strings that represents the list of extension (and subsequent URL) your function or site is allowed to make requests to. This property is required only if your function or site makes external requests.

Build Configuration [build]

The build configuration is used to specify the build settings for the application.

[build]
dir = "build"
entry = "yodelling-coffee-pony_debug.wasm"
command = "npm run build:debug"

[build_release]
dir = "build"
entry = "yodelling-coffee-pony.wasm"
command = "npm run build:release"

[build] Optional

The optional build [build] section contains the settings for building the function in —-debug mode.

[build_release] required

The build_release [build_release] section is used to specify the build settings for the release or production version of your function.

dir string required

The dir field specifies the directory where the build files will be stored.

entry string required

The entry field specifies the name of the entry point for your function. The entry point is the main function that is executed when the application is run.

command string required

The command field specifies the command that will be used to build the application. This field is used to specify the build command for the debug and release versions of the application.

Blockless Extensions

Extensions in Blockless can be thought of as tools or additional functionality that you can integrate into your code to enhance its capabilities. These extensions can either be internal, external, or CGI-based. Here we will discuss each of these extension types, their use cases, and examples.

Internal Extensions

Internal extensions are similar to packages or libraries that you can import into your code. They are compiled together with your WebAssembly (WASM) binary at build time, which means they are part of your final compiled project. This provides the advantage of having all the necessary components and dependencies bundled together, ensuring the proper functioning of your code.

Use Cases

  • When you need specific functionality that is available in a package or library.
  • When you want to reduce the number of external dependencies.
  • When you need to optimize your project for speed and performance.

Example

If you are developing a project in Rust and you need to use a JSON parsing library, you can include the serde_jsoncrate as an internal extension. This will compile the library with your project, allowing you to use its features within your code.

use serde_json::{Value, Error};

fn parse_json(json_str: &str) -> Result<Value, Error> {
serde_json::from_str(json_str)
}

External Extensions

External extensions, or on-demand extensions, are extensions that are installed and managed by the Execution Nodes of the Blockless Network. They can be accessed by your function as needed. These extensions are not compiled with your project but are instead provided by the host machine. This can be helpful in situations where you need access to resources or functionality that is not feasible to include in your binary.

Use Cases

  • When you need access to resources provided by the host machine.
  • When you need to use functionality that cannot be compiled into your WASM binary.
  • When you want to leverage existing system resources or tools

Example

The GETH extension is an example of an external extension. This extension allows you to access an Ethereum node that is present on the host machine. You can use this extension to interact with the Ethereum blockchain, perform transactions, or query data from smart contracts.

CGI Extensions

Common Gateway Interface (CGI) extensions allow you to access packages or libraries that are written in other programming languages. This is useful when you need to use functions or features that are not available in your primary language or when you want to integrate with existing codebases or libraries. CGI extensions essentially export the functions you need and enable you to use them in your own code.

Use Cases

  • When you need to use a library or package that is written in another programming language
  • When you want to integrate with existing codebases or tools
  • When you need access to features or functions that are not available in your primary language

Example

Use the LIT CGI extension to check the validity of a given JWT token:

import "wasi"

import { Console } from "as-wasi/assembly"
import { cgi } from "@blockless/sdk"

// Check whether the extension is available
function isExtensionAvailable(alias: string): bool {
let extensions = cgi.cgiExtendsList()
let isMatch = false

if (extensions && extensions.length > 0) {
for (let i = 0; i < extensions.length; i++) {
const extension = extensions[i]
if (alias === extension.alias) {
isMatch = true
}
}
}

return isMatch
}

// Run the extension
function testLitProtocol(): void {
let command = new cgi.CgiCommand("lit-extension", [], [])
let rs = command.exec()

if (rs === true) {
Console.log(`Verify JWT`)
const verifyJwtResponse = command.callMethod(
'verifyJWT',
[
"eyJhbGciOiJCTFMxMi0zODEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJMSVQiLCJzdWIiOiIweGZmZjE3NWMxNGEyOTllZjcwMjdkYTBkMzQ4ZjQzOGUxNTQ4ODBjY2QiLCJjaGFpbiI6ImV0aGVyZXVtIiwiaWF0IjoxNjc2NDQ0NTcwLCJleHAiOjE2NzY0ODc3NzAsImJhc2VVcmwiOiJsaXQtdGVzdC5ibHMuZGV2IiwicGF0aCI6Ii81Ym9uanB4NHE2Nmoxbng2c2ZoZjEiLCJvcmdJZCI6IiIsInJvbGUiOiIiLCJleHRyYURhdGEiOiIifQ.puWAqp82-1OM-jiHwl2jFroforAU7A5DY_4u9lXZ9KbuPHFcXQB-ovWN9DWfD7DGBf-KxT5_6f5Ii0cHmWi3TAFv-KAVkIYPAX-r_6tV6_ot2mle8pU7f43O_I_mjxwi"
]
)
Console.log(verifyJwtResponse)
}
}

if (isExtensionAvailable('lit-extension')) {
testLitProtocol()
} else {
Console.log('Extension not available.')
}

What’s next?

Now you are familiar with how to use Manifest to configure your function and how to use Extensions to expand the functionality of your function, you should be well-equipped to build exciting applications on Blockless.

Check out how to use the Blockless CLI and Dashboard if you haven’t already. We will release a real-life example of how to create a serverless web app on Blockless soon. Join our community channel now to stay connected!

About Blockless

Blockless is a zk verifiable serverless execution platform that makes dApp building easier than ever.

Website | Twitter | Discord | Telegram | Blog | Medium | Mirror | Linkedin

--

--