Exploring Lit Protocol: Building Lit Actions w/ Lit JS SDK

Exploring Lit Protocol: Building Lit Actions w/ Lit JS SDK

ยท

6 min read

Welcome to the 3rd post of this blog where we will try to discuss about Lit Protocol, how it works, and of course, how to build on top of it.

Before starting, it is worth noting that this is NOT a paid content.

Contents

  • What is Lit Protocol?,

  • Fundamental Concepts;

    • Decentralized Access Control,

    • Programmable Signing,

  • What are Lit Actions?,

  • Building Lit Actions.

What is Lit Protocol?

Lit Protocol is a decentralized network for managing keys that offers developers two primary functions: encryption and programmable signing. While they seem separate, these capabilities collaborate closely and operate based on a unified foundation known as threshold cryptography.

The two main functionality Lit Protocol provides are:

  • Encryption and Decentralized Access Control: Lit Protocol provides data encryption/decryption by utilizing on or off-chain conditions, without relying on a centralized key custodian.
  • Programmable Signing: Lit Protocol can be used to program complex signing automations or provide seamless wallet onboarding experiences using Programmable Key Pairs (PKPs) and Lit Actions.

Fundamental Concepts

Decentralized Access Control

Lit enables a decentralized access control layer that developers can use to encrypt some content and store on the open Web. Thanks to Lit SDK, builders are able to use some utilities provided by Lit Protocol in their applications. They only need to define the access control conditions (ACCs) to determine who will be able to decrypt the encrypted data.

Some other beauty is that Lit supports the use of both on and off-chain data when defining the access control conditions.

Let's see some possible examples:

  • ownership of a particular fungible token or an NFT,

  • KYC info from a central exchange (to enable 'once KYC, use everywhere' functionality),

  • the result of any API call, such as a follow on Twitter,

  • ... and many more.

It is also worth noting that access control conditions are compatible with most EVM chains, Cosmos, and Solana. See the full list.

As you may have already noticed, access control provides us kind of a reading functionality. Now, let's see the other side of the equation to find out how to write data.

Programmable Signing

In order to have the signing feature (to write data to distributed systems, e.g. blockchains), Lit Protocol provides two closely-related services:

  • Programmable Key Pairs (PKP),

  • Lit Actions.

PKPs, which stand for programmable key pairs, are created collaboratively by node operators in the Lit network. These key pairs are stored as distributed key shares. As their name implies, PKPs can be programmed. The set of instructions determining the circumstances under which a PKP will sign, including timing, purpose, and content, is referred to as a Lit Action, which we will deeply dive in the next section.

But simply put, Lit Actions are immutable JavaScript functions. They can be considered as smart contracts.

What are Lit Actions?

Lit Actions are JavaScript codes utilized for specifying signing and authentication rules for PKPs. When utilized alongside PKPs, Lit Actions serve as serverless functions equipped with their own private key-pair. This combination of tools enables the writing of data to blockchains and other similar state machines.

Each Lit Action is executed in parallel across Lit's threshold cryptography network, ensuring that the outcome of each program is independently confirmed by each node. Once a sufficient number of nodes (more than two-thirds of the network participants) have validated the result, the designated signing or decryption process can be carried out.

For instance, a simple illustration involves a Lit Action and its related PKP, which checks whether a number is prime and only yields a signature if the number satisfies the prime condition. Each node executes the Lit Action with a provided input and verifies if it fulfills the specified criteria. Upon meeting the conditions, the node generates an independent key share. The complete signature is only formed after collecting more than two-thirds of these shares.

It is worth noting that Lit Actions are chain-agnostic.

Building Lit Actions

Let us start by installing GetLit CLI:

npm install -g getlit

Install Lit SDK:

npm install @lit-protocol/lit-node-client

As we need our programmable key pair (PKP) to proceed, we will mint a PKP. But to be able to mint a PKP, we need some test LIT tokens. After requesting some test tokens from the Faucet, we can move on:

getlit action
? Where do you want to install the project? ./

๐ŸŽ‰ The project has been installed at /Users/furkan/lit/lit_actions

In order to proceed, we need to modify 'NA_E' to 'NAME' in src/foo.action.ts:

/**
 * NA_E: foo
 *
 * โฌ†๏ธ Replace "_" with "M" to pass the schema validation
 *
 */

const foo = () => {
  return "bar";
};

Now, we need to mint a PKP:

getlit setup

This command redirects us to the browser:

Here we see some PKPs I've already minted, but we will mint a new one. Let us click on the 'Mint PKP!' button:

Confirm the transaction:

As you can see, now we have the minted PKP. After selecting it, we can get back to the terminal:

๐Ÿ” Listening at http://localhost:1210/auth to get your authSig and pkpPublicKey

authSig: {
  sig: '0xdb2171826a7d4f9d617e1ae94358f25227ff102b2b0ff7d362a3d95e237a97d11d5aa14075efa7e4bc92f805fb85a444320f4716d834d49cb9fa97de09b28ba21b',
  derivedVia: 'web3.eth.personal.sign',
  signedMessage: 'localhost:1210 wants you to sign in with your Ethereum account:\n' +
    '0x10A7a427aA5644CEc46462092c2e4354fe840dc1\n' +
    '\n' +
    '\n' +
    'URI: http://localhost:1210/auth\n' +
    'Version: 1\n' +
    'Chain ID: 1\n' +
    'Nonce: 7u1ZmKDg1CwP9NFoA\n' +
    'Issued At: 2023-10-31T11:49:22.456Z\n' +
    'Expiration Time: 2023-11-01T11:49:15.023Z',
  address: '0x10a7a427aa5644cec46462092c2e4354fe840dc1'
}
pkpPublicKey: 0x047b32ee581b66473d342cb3ac71538450e843a876c19e4097e806abbb4ca2ed3ff757f27f05699ea5e22d5fd3b4b87418f3a6ec470a70275a833ad19021ceecff

๐ŸŽ‰ Success! Your authSig and pkpPublicKey have been saved to your config file.
   You can view your config file at /Users/furkan/lit/lit_actions/getlit.json

Before we continue, let's see what we have in src/main.action.ts:

/**
 * NAME: hello
 */

// This will exceed the default file size limit
// import * as LitJsSdk from "@lit-protocol/lit-node-client-nodejs";

type SignData = number[];

const helloWorld: SignData = [
  72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100,
];

(async () => {
  // this requests a signature share from the Lit Node
  // the signature share will be automatically returned in the HTTP response from the node
  const sigShare = await LitActions.signEcdsa({
    toSign: new Uint8Array(helloWorld),
    publicKey, // <-- You should pass this in jsParam
    sigName,
  });

  console.log('sigShare', sigShare);
})();

This code basically:

  • defines an array called 'helloWorld' setting the encrypted version of the letters of 'Hello world' string,

  • signs our encrypted array with the help of our pkpPublicKey, using 'signEcdsa' method,

  • prints the result.

Now we have two Lit Actions:

  • foo,

  • main.

You can test them by running the test command, or create a new lit action by running the 'getlit action' command and continue building.

ย