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
orsessionSigs
, 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
orsessionSigs
, 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
orsessionSigs
, 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
orsessionSigs
, 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
orsessionSigs
, 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
orsessionSigs
, 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
orsessionSigs
, 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
orsessionSigs
, 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 š