New Release: SDK v6

New Release: SDK v6

The latest version of the Lit SDK, v6, has just been released. Included are several improvements, feature additions, and breaking changes all aimed at enhancing the overall performance of the Lit SDK and developer experience on Lit. You can access the latest build (live on the Cayenne network) here.

Here's everything you need to know about the latest changes and additions:

🚨 Breaking Changes & Important Updates

The most significant change in v6 is the combination of authSig and sessionSigs. In most functions, the client-side generated authSig will no longer be accepted as an argument, as seen in commonly used functions like executeJs and pkpSign. Instead, it will be used to generate sessionSigs to authenticate with the Lit nodes.

Per-Package Changes

@lit-protocol/lit-node-client

executeJs

  • v5 - optional use of authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const res = await litNodeClient.executeJs({
	authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});

// v6 
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const res = await litNodeClient.executeJs({
	sessionSigs,
	...
});

pkpSign

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const res = await litNodeClient.pkpSign({
	authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});

// v6
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const res = await litNodeClient.pkpSign({
	sessionSigs,
	...
});

@lit-protocol/encryption

encryptString

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const encryptedString = await LitJsSdk.encryptString({
  authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});
  
// v6
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const encryptedString = await LitJsSdk.encryptString({
  sessionSigs,
	...
});

decryptToString

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const decryptedString = await LitJsSdk.decryptToString({
  authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});
  
// v6
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const decryptedString = await LitJsSdk.decryptToString({
  sessionSigs,
	...
});

encryptToJson

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const encryptedJsonStr = await LitJsSdk.encryptToJson({
  authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});
  
// v6
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const encryptedJsonStr = await LitJsSdk.encryptToJson({
  sessionSigs,
	...
});

decryptFromJson

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const decryptedFile = await LitJsSdk.decryptFromJson({
  authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});
  
// v6
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const decryptedFile = await LitJsSdk.decryptFromJson({
  sessionSigs,
	...
});

encryptFileAndZipWithMetadata

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const encryptedData = await LitJsSdk.encryptFileAndZipWithMetadata({
  authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});
  
// v6
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const encryptedData = await LitJsSdk.encryptFileAndZipWithMetadata({
  sessionSigs,
	...
});

decryptZipFileWithMetadata

  • v5 - optional authSig or sessionSigs, but either must exist.
  • v6 - sessionSigs is strictly required
// v5
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { AuthSig, SessionSigsMap } from '@lit-protocol/types';

const authSig: AuthSig = '...';
const sessionSigs: SessionSigsMap = '...';

const decryptedData = await LitJsSdk.decryptZipFileWithMetadata({
  authSig?: authSig,
	sessionSigs?: sessionSigs;
	...
});
  
// v6
import * as LitJsSdk from '@lit-protocol/lit-node-client';
import { SessionSigsMap } from '@lit-protocol/types';

const sessionSigs: SessionSigsMap = '...';

const decryptedData = await LitJsSdk.decryptZipFileWithMetadata({
  sessionSigs,
	...
});

@lit-protocol/constants

Getting Lit supported curves

SIGTYPE to LIT_CURVE

// v5
import { SIGTYPE } from '@lit-protocol/constants'

export enum SIGTYPE {
  BLS = 'BLS',
  EcdsaK256 = 'K256',
  EcdsaCaitSith = 'ECDSA_CAIT_SITH', 
  EcdsaCAITSITHP256 = 'EcdsaCaitSithP256',
}

// v6
import { LIT_CURVE } from '@lit-protocol/constants'

export enum LIT_CURVE {
  BLS = 'BLS',
  EcdsaK256 = 'K256',
  EcdsaCaitSith = 'ECDSA_CAIT_SITH',
  EcdsaCAITSITHP256 = 'EcdsaCaitSithP256',
}

🛠️ Enhancements, Fixes, and Additions

signSessionKey

In the signSessionKey parameters, we've added three extra optional arguments for custom authentication. These arguments allow you to use your PKP to conditionally sign (via custom Lit Action code) the session key on the Lit nodes. For context, this function is typically used as the callback function for the authNeededCallback parameter of getSessionSigs.

For simplicity, we introduced getPkpSessionSigs, which uses signSessionKey under the hood.

// v5
const response = await this.signSessionKey({
  sessionKey: props.sessionKey,
  statement: props.statement || 'Some custom statement.',
  authMethods: [...params.authMethods],
  pkpPublicKey: params.pkpPublicKey,
  expiration: props.expiration,
  resources: props.resources,
  chainId: 1,
  resourceAbilityRequests: props.resourceAbilityRequests,
});

// v6
const response = await this.signSessionKey({
  sessionKey: props.sessionKey,
  statement: props.statement || 'Some custom statement.',
  authMethods: [...params.authMethods],
  pkpPublicKey: params.pkpPublicKey,
  expiration: props.expiration,
  resources: props.resources,
  chainId: 1,
  resourceAbilityRequests: props.resourceAbilityRequests,

  // -- optional fields
  ...(props.litActionCode && { litActionCode: props.litActionCode }),
  ...(props.ipfsId && { ipfsId: props.ipfsId }),
  ...(props.jsParams && { jsParams: props.jsParams }),
});

getPkpSessionSigs

Rather than creating a callback for the authNeededCallback parameter in the getSessionSigs function, this function creates the callback and signs the session key under the hood using the signSessionKey function.

import { EthWalletProvider } from '@lit-protocol/lit-auth-client';

// -- preparing the parameters
const authMethod = await EthWalletProvider.authenticate({
  signer: YOUR_WALLET_SIGNER,
  litNodeClient,
});

const authMethodOwnedPkpPublicKey = '0x..';

const resourceAbilityRequests = [
  {
    resource: new LitPKPResource('*'),
    ability: LitAbility.PKPSigning,
  },
  {
    resource: new LitActionResource('*'),
    ability: LitAbility.LitActionExecution,
  },
];

// -- get pkp session sigs
const pkpSessionSigs = await litNodeClient.getPkpSessionSigs({
  pkpPublicKey: authMethodOwnedPkpPublicKey,
  authMethods: [authMethod],
  resourceAbilityRequests: resourceAbilityRequests,
});

Custom Authentication

For custom authentication, you can set custom Javascript code that would be executed on Lit Action.

import { EthWalletProvider } from '@lit-protocol/lit-auth-client';

// -- preparing the parameters
const authMethod = await EthWalletProvider.authenticate({
  signer: YOUR_WALLET_SIGNER,
  litNodeClient,
});

const authMethodOwnedPkpPublicKey = '0x..';

const resourceAbilityRequests = [
  {
    resource: new LitPKPResource('*'),
    ability: LitAbility.PKPSigning,
  },
  {
    resource: new LitActionResource('*'),
    ability: LitAbility.LitActionExecution,
  },
];

// In a browser environment, instead of using Node.js's Buffer class 
// for handling binary data and encoding it to base64, 
// you can use the TextEncoder API to convert string data to a 
// Uint8Array and then convert it to a base64 string using btoa() function.
const customAuthLitActionCode = Buffer.from(`
// Works with an AuthSig AuthMethod
if (Lit.Auth.authMethodContexts.some(e => e.authMethodType === 1)) {
  LitActions.setResponse({ response: "true" });
} else {
  LitActions.setResponse({ response: "false" });
}
`).toString('base64');

// -- get pkp session sigs with custom authentication
const litActionSessionSigs = await litNodeClient.getPkpSessionSigs({
  pkpPublicKey: authMethodOwnedPkpPublicKey,
  authMethods: [authMethod],
  resourceAbilityRequests: resourceAbilityRequests,
  litActionCode: customAuthLitActionCode,
  jsParams: {
    publicKey: authMethodOwnedPkpPublicKey,
    sigName: 'custom-auth',
  }
});

Crafting SIWE messages

Ever had to craft your SIWE message but were confused about the arguments to pass in? With v6, we have introduced the following helper functions:

createSiweMessage

This versatile function allows users to generate any type of SIWE message, making it perfect for advanced users. For convenience, all optional fields are pre-filled with default values. However, we recommend changing the pre-filled values for production use.

import { createSiweMessage } from '@lit-protocol/auth-helper';

// return siweMessage.prepareMessage()
const toSign : string = await createSiweMessage({
  walletAddress: '',
  nonce: await litNodeClient.getLatestBlockhash()
})

createSiweMessageWithRecaps

Unlike createSiteMessage, this function strictly requires the uri, expiration, and resources arguments. It's usually used as a callback argument for the authNeededCallback parameter in the getSessionSigs function for EOA wallets.

import { createSiweMessageWithRecaps } from '@lit-protocol/auth-helper';

// return siweMessage.prepareMessage()
const toSign = await createSiweMessageWithRecaps({
  uri: callbackParams.uri,
  expiration: callbackParams.expiration,
  resources: callbackParams.resourceAbilityRequests,
  walletAddress: person.wallet.address,
  nonce: await litNodeClient.getLatestBlockhash(),
  litNodeClient: devEnv.litNodeClient,
});

Generate an authSig

generateAuthSig

As stated in the description, we still need to use authSig mainly to generate sessionSigs which are now the only type accepted by the Lit nodes. By utilising the generateAuthSig function, we can ensure the structure of the authSig object is correct.

import { 
	generateAuthSig,
	createSiweMessageWithRecaps
} from '@lit-protocol/auth-helper';

const wallet = new ethers.Wallet.createRandom();
const preparedSiweMessage = await createSiweMessageWithRecap({...})

const authSig = await generateAuthSig({
  signer: wallet,
  toSign: preparedSiweMessage,
});

🧐 Clarifications

createCapacityDelegationAuthSig

There has been some confusion on the parameters for createCapacityDelegationAuthSig, particularly capacityTokenId, delegateeAddresses, and uses when delegating capacity credits.

Below is a table detailing the expected behaviors of each:

Parameter Provided with Values Not Provided Provided but Empty Array
capacityTokenId Scopes the delegation to specific NFTs identified by the IDs in the array. The function will only consider the NFTs whose IDs are listed. All NFTs owned by the user are considered eligible under the delegation. The delegation applies universally to all NFTs the user owns. N/A
delegateeAddresses Restricts the use of the delegation to the addresses listed in the array. Only users whose addresses are included can utilise the delegated capabilities. The delegation is universally applicable to anyone. There are no restrictions on who can use the delegated capabilities. No one is allowed to use the delegated capabilities since there are no valid user addresses specified.
uses Sets a limit on the number of times the delegation can be used. The function enforces this limit and prevents use beyond it. There is no limit on the number of times the delegation can be used. The capability can be used indefinitely. Theoretically, an empty value for uses would mean no uses are possible, effectively disabling the delegation, but typically this scenario should either not be allowed by schema/logic or treated as zero, which also disables the delegation.

Installing the SDK

Install the @lit-protocol/lit-node-client package, which can be used in both browser and Node environments:

yarn add @lit-protocol/lit-node-client

Use the Lit JS SDK v6:

import * as LitJsSdk from "@lit-protocol/lit-node-client";

Get started here.

Looking Forward

We are continuing to work hard to ensure the development process on Lit is smooth and pain-free!

As always, we're eager to hear your feedback and experiences with the new release. Your insights are invaluable in helping us continue to refine and improve the Lit SDK going forward.

You can join the Lit developer ecosystem on Discord and Telegram. We are eager to hear from you there 🙂