Lit Protocol Integration Guide
LitProtocol is distributed cryptography for signing, encryption, and compute. A generalizable key management network, Lit provides developers with a set of tools for managing sovereign identities on the open Web.
Combining Lit Protocol's pkp wallet with Account Kit allows you to use your Programmable Key Pairs (PKPs) as a smart account for your users.
WARNING
Lit Protocol's pkp network is still in testnet. Backwards compatibility, and data availability will not be guaranteed until mainnet. Do not use PKP wallets to store valuable assets.
Integration
Install the pkp ethers package
bash
npm i @lit-protocol/pkp-ethers@cayenne
npm i @lit-protocol/pkp-ethers@cayenne
bash
yarn add @lit-protocol/pkp-ethers@cayenne
yarn add @lit-protocol/pkp-ethers@cayenne
Install the LitNodeClient
bash
npm i @lit-protocol/lit-node-client@cayenne
npm i @lit-protocol/lit-node-client@cayenne
bash
yarn add @lit-protocol/lit-node-client@cayenne
yarn add @lit-protocol/lit-node-client@cayenne
Creating PKP
See documentation here for creating PKPs
Create a SmartAccountSigner
Next, setup the LitNodeClient
and PKPEthersWallet
to create a SmartAccountSigner
:
ts
import { WalletClientSigner, type SmartAccountSigner } from "@alchemy/aa-core";
import { LitAbility, LitActionResource } from "@lit-protocol/auth-helpers";
import { LitNodeClient } from "@lit-protocol/lit-node-client";
import { PKPEthersWallet } from "@lit-protocol/pkp-ethers";
import { AuthCallbackParams } from "@lit-protocol/types";
import { createWalletClient, custom } from "viem";
import { polygonMumbai } from "viem/chains";
const API_KEY = "<YOUR API KEY>";
const POLYGON_MUMBAI_RPC_URL = `${polygonMumbai.rpcUrls.alchemy.http[0]}/${API_KEY}`;
const PKP_PUBLIC_KEY = "<YOUR PKP PUBLIC KEY>";
const litNodeClient = new LitNodeClient({
litNetwork: "cayenne",
debug: false,
});
await litNodeClient.connect();
const resourceAbilities = [
{
resource: new LitActionResource("*"),
ability: LitAbility.PKPSigning,
},
];
/**
* For provisioning keys and setting up authentication methods see documentation below
* https://developer.litprotocol.com/v2/pkp/minting
*/
const authNeededCallback = async (params: AuthCallbackParams) => {
const response = await litNodeClient.signSessionKey({
sessionKey: params.sessionKeyPair,
statement: params.statement,
authMethods: [],
pkpPublicKey: PKP_PUBLIC_KEY,
expiration: params.expiration,
resources: params.resources,
chainId: 1,
});
return response.authSig;
};
const sessionSigs = await litNodeClient
.getSessionSigs({
chain: "ethereum",
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toISOString(),
resourceAbilityRequests: resourceAbilities,
authNeededCallback,
})
.catch((err) => {
console.log("error while attempting to access session signatures: ", err);
throw err;
});
const pkpWallet = new PKPEthersWallet({
pkpPubKey: PKP_PUBLIC_KEY,
rpc: POLYGON_MUMBAI_RPC_URL,
controllerSessionSigs: sessionSigs,
});
// a smart account signer you can use as an owner on ISmartContractAccount
export const litSigner: SmartAccountSigner = new WalletClientSigner(
createWalletClient({ transport: custom(pkpWallet.rpcProvider) }), // JsonRpcProvider instance,
"lit" // signerType
);
import { WalletClientSigner, type SmartAccountSigner } from "@alchemy/aa-core";
import { LitAbility, LitActionResource } from "@lit-protocol/auth-helpers";
import { LitNodeClient } from "@lit-protocol/lit-node-client";
import { PKPEthersWallet } from "@lit-protocol/pkp-ethers";
import { AuthCallbackParams } from "@lit-protocol/types";
import { createWalletClient, custom } from "viem";
import { polygonMumbai } from "viem/chains";
const API_KEY = "<YOUR API KEY>";
const POLYGON_MUMBAI_RPC_URL = `${polygonMumbai.rpcUrls.alchemy.http[0]}/${API_KEY}`;
const PKP_PUBLIC_KEY = "<YOUR PKP PUBLIC KEY>";
const litNodeClient = new LitNodeClient({
litNetwork: "cayenne",
debug: false,
});
await litNodeClient.connect();
const resourceAbilities = [
{
resource: new LitActionResource("*"),
ability: LitAbility.PKPSigning,
},
];
/**
* For provisioning keys and setting up authentication methods see documentation below
* https://developer.litprotocol.com/v2/pkp/minting
*/
const authNeededCallback = async (params: AuthCallbackParams) => {
const response = await litNodeClient.signSessionKey({
sessionKey: params.sessionKeyPair,
statement: params.statement,
authMethods: [],
pkpPublicKey: PKP_PUBLIC_KEY,
expiration: params.expiration,
resources: params.resources,
chainId: 1,
});
return response.authSig;
};
const sessionSigs = await litNodeClient
.getSessionSigs({
chain: "ethereum",
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toISOString(),
resourceAbilityRequests: resourceAbilities,
authNeededCallback,
})
.catch((err) => {
console.log("error while attempting to access session signatures: ", err);
throw err;
});
const pkpWallet = new PKPEthersWallet({
pkpPubKey: PKP_PUBLIC_KEY,
rpc: POLYGON_MUMBAI_RPC_URL,
controllerSessionSigs: sessionSigs,
});
// a smart account signer you can use as an owner on ISmartContractAccount
export const litSigner: SmartAccountSigner = new WalletClientSigner(
createWalletClient({ transport: custom(pkpWallet.rpcProvider) }), // JsonRpcProvider instance,
"lit" // signerType
);
Use it with LightAccount
We can link our SmartAccountSigner
to a LightSmartContractAccount
from aa-accounts
:
ts
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import {
LightSmartContractAccount,
getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { litSigner } from "./lit";
const chain = sepolia;
const provider = new AlchemyProvider({
apiKey: "ALCHEMY_API_KEY",
chain,
}).connect(
(rpcClient) =>
new LightSmartContractAccount({
chain,
owner: litSigner,
factoryAddress: getDefaultLightAccountFactoryAddress(chain),
rpcClient,
})
);
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import {
LightSmartContractAccount,
getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { litSigner } from "./lit";
const chain = sepolia;
const provider = new AlchemyProvider({
apiKey: "ALCHEMY_API_KEY",
chain,
}).connect(
(rpcClient) =>
new LightSmartContractAccount({
chain,
owner: litSigner,
factoryAddress: getDefaultLightAccountFactoryAddress(chain),
rpcClient,
})
);
ts
import { WalletClientSigner, type SmartAccountSigner } from "@alchemy/aa-core";
import { LitAbility, LitActionResource } from "@lit-protocol/auth-helpers";
import { LitNodeClient } from "@lit-protocol/lit-node-client";
import { PKPEthersWallet } from "@lit-protocol/pkp-ethers";
import { AuthCallbackParams } from "@lit-protocol/types";
import { createWalletClient, custom } from "viem";
import { polygonMumbai } from "viem/chains";
const API_KEY = "<YOUR API KEY>";
const POLYGON_MUMBAI_RPC_URL = `${polygonMumbai.rpcUrls.alchemy.http[0]}/${API_KEY}`;
const PKP_PUBLIC_KEY = "<YOUR PKP PUBLIC KEY>";
const litNodeClient = new LitNodeClient({
litNetwork: "cayenne",
debug: false,
});
await litNodeClient.connect();
const resourceAbilities = [
{
resource: new LitActionResource("*"),
ability: LitAbility.PKPSigning,
},
];
/**
* For provisioning keys and setting up authentication methods see documentation below
* https://developer.litprotocol.com/v2/pkp/minting
*/
const authNeededCallback = async (params: AuthCallbackParams) => {
const response = await litNodeClient.signSessionKey({
sessionKey: params.sessionKeyPair,
statement: params.statement,
authMethods: [],
pkpPublicKey: PKP_PUBLIC_KEY,
expiration: params.expiration,
resources: params.resources,
chainId: 1,
});
return response.authSig;
};
const sessionSigs = await litNodeClient
.getSessionSigs({
chain: "ethereum",
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toISOString(),
resourceAbilityRequests: resourceAbilities,
authNeededCallback,
})
.catch((err) => {
console.log("error while attempting to access session signatures: ", err);
throw err;
});
const pkpWallet = new PKPEthersWallet({
pkpPubKey: PKP_PUBLIC_KEY,
rpc: POLYGON_MUMBAI_RPC_URL,
controllerSessionSigs: sessionSigs,
});
// a smart account signer you can use as an owner on ISmartContractAccount
export const litSigner: SmartAccountSigner = new WalletClientSigner(
createWalletClient({ transport: custom(pkpWallet.rpcProvider) }), // JsonRpcProvider instance,
"lit" // signerType
);
import { WalletClientSigner, type SmartAccountSigner } from "@alchemy/aa-core";
import { LitAbility, LitActionResource } from "@lit-protocol/auth-helpers";
import { LitNodeClient } from "@lit-protocol/lit-node-client";
import { PKPEthersWallet } from "@lit-protocol/pkp-ethers";
import { AuthCallbackParams } from "@lit-protocol/types";
import { createWalletClient, custom } from "viem";
import { polygonMumbai } from "viem/chains";
const API_KEY = "<YOUR API KEY>";
const POLYGON_MUMBAI_RPC_URL = `${polygonMumbai.rpcUrls.alchemy.http[0]}/${API_KEY}`;
const PKP_PUBLIC_KEY = "<YOUR PKP PUBLIC KEY>";
const litNodeClient = new LitNodeClient({
litNetwork: "cayenne",
debug: false,
});
await litNodeClient.connect();
const resourceAbilities = [
{
resource: new LitActionResource("*"),
ability: LitAbility.PKPSigning,
},
];
/**
* For provisioning keys and setting up authentication methods see documentation below
* https://developer.litprotocol.com/v2/pkp/minting
*/
const authNeededCallback = async (params: AuthCallbackParams) => {
const response = await litNodeClient.signSessionKey({
sessionKey: params.sessionKeyPair,
statement: params.statement,
authMethods: [],
pkpPublicKey: PKP_PUBLIC_KEY,
expiration: params.expiration,
resources: params.resources,
chainId: 1,
});
return response.authSig;
};
const sessionSigs = await litNodeClient
.getSessionSigs({
chain: "ethereum",
expiration: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toISOString(),
resourceAbilityRequests: resourceAbilities,
authNeededCallback,
})
.catch((err) => {
console.log("error while attempting to access session signatures: ", err);
throw err;
});
const pkpWallet = new PKPEthersWallet({
pkpPubKey: PKP_PUBLIC_KEY,
rpc: POLYGON_MUMBAI_RPC_URL,
controllerSessionSigs: sessionSigs,
});
// a smart account signer you can use as an owner on ISmartContractAccount
export const litSigner: SmartAccountSigner = new WalletClientSigner(
createWalletClient({ transport: custom(pkpWallet.rpcProvider) }), // JsonRpcProvider instance,
"lit" // signerType
);