From bb16b3827bf3d53b260c6ef47942490eda80f923 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:07:06 -0500 Subject: [PATCH 01/10] Delete packages/plugin-lit/src/providers directory --- packages/plugin-lit/src/providers/index.ts | 2 - .../plugin-lit/src/providers/litProvider.ts | 287 ------------------ .../src/providers/pkpPermissionsProvider.ts | 46 --- 3 files changed, 335 deletions(-) delete mode 100644 packages/plugin-lit/src/providers/index.ts delete mode 100644 packages/plugin-lit/src/providers/litProvider.ts delete mode 100644 packages/plugin-lit/src/providers/pkpPermissionsProvider.ts diff --git a/packages/plugin-lit/src/providers/index.ts b/packages/plugin-lit/src/providers/index.ts deleted file mode 100644 index cd64b247d4c..00000000000 --- a/packages/plugin-lit/src/providers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./litProvider"; -export * from "./pkpPermissionsProvider"; diff --git a/packages/plugin-lit/src/providers/litProvider.ts b/packages/plugin-lit/src/providers/litProvider.ts deleted file mode 100644 index 24646448f36..00000000000 --- a/packages/plugin-lit/src/providers/litProvider.ts +++ /dev/null @@ -1,287 +0,0 @@ -import { Provider, Memory, State, IAgentRuntime } from "@elizaos/core"; -import { LitNodeClient } from "@lit-protocol/lit-node-client"; -import { LitContracts } from "@lit-protocol/contracts-sdk"; -import { LIT_RPC, LIT_NETWORK } from "@lit-protocol/constants"; -import { AuthSig } from "@lit-protocol/auth-helpers"; -import { PKPEthersWallet } from "@lit-protocol/pkp-ethers"; -import * as ethers from "ethers"; -import { LitConfigManager, LitConfig } from "../config/configManager.ts"; -import * as solanaWeb3 from "@solana/web3.js"; - -export interface LitState { - nodeClient: LitNodeClient; - contractClient: LitContracts; - authSig?: AuthSig; - network?: string; - evmWallet?: ethers.Wallet; - pkp?: { - tokenId: string; - publicKey: string; - ethAddress: string; - solanaAddress?: string; - }; - capacityCredit?: { - tokenId: string; - }; -} - -let executionCount = 0; - -// Add a flag to track if the function is already running -let isExecutionInProgress = false; - -export const litProvider: Provider = { - get: async ( - runtime: IAgentRuntime, - _message: Memory, - state?: State & { lit?: LitState } - ) => { - // Guard against re-execution - if (isExecutionInProgress) { - console.log("Execution already in progress, skipping..."); - return; - } - - try { - isExecutionInProgress = true; - - // Initialize config manager - const configManager = new LitConfigManager(); - - // Try to load existing config - const savedConfig = configManager.loadConfig(); - - const provider = new ethers.providers.StaticJsonRpcProvider({ - url: LIT_RPC.CHRONICLE_YELLOWSTONE, - skipFetchSetup: true, - }); - - // If we have saved config and no current state, initialize state from config - if (savedConfig && !state?.lit?.pkp) { - if (!state!.lit) { - state!.lit = {} as LitState; - } - state!.lit.pkp = savedConfig.pkp; - state!.lit.network = savedConfig.network; - state!.lit.capacityCredit = savedConfig.capacityCredit; - - // Initialize wallet from saved private key - if (savedConfig.evmWalletPrivateKey) { - state!.lit.evmWallet = new ethers.Wallet( - savedConfig.evmWalletPrivateKey, - provider - ); - } - - // Verify the saved config is still valid - const isValid = await configManager.verifyConfig(savedConfig); - if (!isValid) { - console.log("Saved config is invalid, will create new PKP"); - state!.lit.pkp = undefined; - state!.lit.evmWallet = undefined; - } - } - - // Strengthen the check for existing initialization - if (state?.lit?.nodeClient && state?.lit?.contractClient) { - console.log("📝 Reusing existing Lit environment", { - network: state.lit.network, - pkpAddress: state?.lit?.pkp?.ethAddress, - }); - return `Reusing existing Lit environment on network ${state.lit.network}`; - } - - // Only proceed with initialization if we don't have all required components - - // Initialize basic Lit client if not exists - const litNodeClient = - state?.lit?.nodeClient || - new LitNodeClient({ - litNetwork: LIT_NETWORK.DatilTest, - debug: false, - }); - - if (!state?.lit?.nodeClient) { - await litNodeClient.connect(); - console.log("✅ Connected to the Lit network"); - } - - const thisExecution = ++executionCount; - console.log(`Starting execution #${thisExecution}`, { - hasExistingClient: !!state?.lit?.nodeClient, - messageId: _message?.id, // If messages have IDs - }); - - const network = await provider.getNetwork(); - const networkName = - network.name !== "unknown" - ? network.name - : `Chain ID ${network.chainId}`; - - // Create funding wallet with provider - const fundingWallet = new ethers.Wallet( - runtime.getSetting("FUNDING_PRIVATE_KEY"), - provider - ); - - // Initialize evmWallet first - let evmWallet = - state!.lit?.evmWallet || ethers.Wallet.createRandom().connect(provider); - state!.lit = - state!.lit || - ({ - nodeClient: litNodeClient, - contractClient: {} as LitContracts, - wallet: {} as PKPEthersWallet, - evmWallet: evmWallet, - } as LitState); - - // Initialize contract client with evmWallet as signer - const contractClient = new LitContracts({ - network: LIT_NETWORK.DatilTest, - signer: evmWallet, - }); - await contractClient.connect(); - console.log("✅ Connected LitContracts client to network"); - - let pkpPublicKey = - runtime.getSetting("LIT_PKP_PUBLIC_KEY") || state?.lit?.pkp?.publicKey; - - // If no PKP exists, mint a new one - if (!pkpPublicKey) { - console.log("🔄 No PKP found. Creating new dual wallet..."); - - if (!state!.lit) { - state!.lit = {} as LitState; - } - let evmWallet = - state!.lit.evmWallet || - ethers.Wallet.createRandom().connect(provider); - - // Make sure to store the wallet in the state - state!.lit.evmWallet = evmWallet; - - // Generate Solana Wallet - const svmWallet = solanaWeb3.Keypair.generate(); - - // Check the balance of the funding wallet - const balance = await provider.getBalance(fundingWallet.address); - console.log( - `Funding wallet balance: ${ethers.utils.formatEther(balance)} tstLPX` - ); - - // Fund the EVM wallet first - try { - console.log("Funding new EVM wallet with gas..."); - - const tx = await fundingWallet.sendTransaction({ - to: evmWallet.address, - value: ethers.utils.parseEther("0.006"), - gasLimit: 21000, - }); - - console.log(`Funding transaction sent. Hash: ${tx.hash}`); - const receipt = await tx.wait(); - console.log("💰 EVM Wallet funded successfully", { - gasUsed: receipt.gasUsed.toString(), - fundedAmount: "0.006", - }); - - const mintResult = - await contractClient.pkpNftContractUtils.write.mint(); - - console.log("✅ Dual PKP minted:", { - tokenId: mintResult.pkp.tokenId, - publicKey: mintResult.pkp.publicKey, - ethAddress: mintResult.pkp.ethAddress, - solanaAddress: svmWallet.publicKey.toString(), - }); - - pkpPublicKey = mintResult.pkp.publicKey; - - if (!state!.lit) { - state!.lit = {} as LitState; - } - - state!.lit.pkp = { - tokenId: mintResult.pkp.tokenId, - publicKey: mintResult.pkp.publicKey, - ethAddress: mintResult.pkp.ethAddress, - solanaAddress: svmWallet.publicKey.toString(), - }; - - const newConfig: LitConfig = { - pkp: { - tokenId: mintResult.pkp.tokenId, - publicKey: mintResult.pkp.publicKey, - ethAddress: mintResult.pkp.ethAddress, - solanaAddress: svmWallet.publicKey.toString(), - }, - network: networkName, - timestamp: Date.now(), - evmWalletPrivateKey: evmWallet.privateKey, - solanaWalletPrivateKey: Buffer.from(svmWallet.secretKey).toString('base64'), - }; - - configManager.saveConfig(newConfig); - } catch (error) { - console.error("Failed to mint dual PKP:", error); - throw error; - } - } - - // Mint capacity credit if not exists - if (!state!.lit?.capacityCredit?.tokenId) { - const capacityCreditClient = new LitContracts({ - network: LIT_NETWORK.DatilTest, - signer: fundingWallet, - }); - await capacityCreditClient.connect(); - console.log("🔄 Minting Capacity Credit NFT..."); - const capacityCreditInfo = - await capacityCreditClient.mintCapacityCreditsNFT({ - requestsPerKilosecond: 80, - daysUntilUTCMidnightExpiration: 1, - }); - - // Store the capacity credit token ID - state!.lit!.capacityCredit = { - tokenId: capacityCreditInfo.capacityTokenIdStr, // This is your resource ID - }; - console.log( - `✅ Minted Capacity Credit with ID: ${capacityCreditInfo.capacityTokenIdStr}` - ); - - // Save the updated config with capacity credit - const currentConfig = configManager.loadConfig(); - const updatedConfig: LitConfig = { - ...currentConfig, - capacityCredit: { - tokenId: capacityCreditInfo.capacityTokenIdStr, - }, - timestamp: Date.now(), - }; - configManager.saveConfig(updatedConfig); - } - - // Update state with the initialized wallet and other components - state!.lit = { - nodeClient: litNodeClient, - contractClient, - network: networkName, - evmWallet: evmWallet, - pkp: state!.lit?.pkp || { - tokenId: state!.lit?.pkp?.tokenId, - publicKey: pkpPublicKey, - ethAddress: state!.lit?.pkp?.ethAddress, - solanaAddress: state!.lit?.pkp?.solanaAddress, - }, - capacityCredit: state!.lit?.capacityCredit, - }; - - return `Lit environment initialized with network ${networkName}`; - } finally { - isExecutionInProgress = false; - } - }, -}; diff --git a/packages/plugin-lit/src/providers/pkpPermissionsProvider.ts b/packages/plugin-lit/src/providers/pkpPermissionsProvider.ts deleted file mode 100644 index 8a8b31b0ee2..00000000000 --- a/packages/plugin-lit/src/providers/pkpPermissionsProvider.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { IAgentRuntime, Memory, State } from "@elizaos/core"; -import { AUTH_METHOD_SCOPE } from "@lit-protocol/constants"; -import { BigNumber, utils } from "ethers"; -import { LitContracts } from "@lit-protocol/contracts-sdk"; -import { LitNodeClient } from "@lit-protocol/lit-node-client"; - -interface LitState { - contractClient: LitContracts; - nodeClient: LitNodeClient; - authSig: { - sig: string; - derivedVia: string; - signedMessage: string; - address: string; - }; -} - -export const pkpPermissionsProvider = { - addPermissions: async ( - _runtime: IAgentRuntime, - _message: Memory, - state: State, - tokenId: string, - authMethod: { - authMethodType: number; - id: string; - userPubkey: string; - }, - scopes: (typeof AUTH_METHOD_SCOPE)[] - ) => { - const { contractClient } = (state.lit || {}) as LitState; - if (!contractClient) { - throw new Error("Lit contracts client not available"); - } - - const tx = - await contractClient.pkpPermissionsContract.write.addPermittedAuthMethod( - tokenId, - authMethod, - scopes.map((s) => BigNumber.from(s)), - { gasPrice: utils.parseUnits("1", "gwei"), gasLimit: 400000 } - ); - await tx.wait(); - return `Permissions added to PKP ${tokenId}`; - }, -}; From e9ac6ad6c6e30708276a9188bb641b30da2b2cb5 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:07:14 -0500 Subject: [PATCH 02/10] Delete packages/plugin-lit/src/config directory --- .../plugin-lit/src/config/configManager.ts | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 packages/plugin-lit/src/config/configManager.ts diff --git a/packages/plugin-lit/src/config/configManager.ts b/packages/plugin-lit/src/config/configManager.ts deleted file mode 100644 index 02c412e1906..00000000000 --- a/packages/plugin-lit/src/config/configManager.ts +++ /dev/null @@ -1,55 +0,0 @@ -import fs from "node:fs"; -import path from "node:path"; - -export interface LitConfig { - pkp: { - tokenId: string; - publicKey: string; - ethAddress: string; - solanaAddress?: string; - }; - network: string; - timestamp: number; - evmWalletPrivateKey: string; - solanaWalletPrivateKey?: string; - wrappedKeyId?: string; - capacityCredit?: { - tokenId: string; - }; -} - -export class LitConfigManager { - private configPath: string; - - constructor() { - this.configPath = path.join(process.cwd(), "lit-config.json"); - console.log("LitConfigManager initialized with path:", this.configPath); - } - - loadConfig(): LitConfig | null { - try { - if (fs.existsSync(this.configPath)) { - const config = JSON.parse(fs.readFileSync(this.configPath, "utf8")); - return config; - } - } catch (error) { - console.error("Error loading config:", error); - } - return null; - } - - saveConfig(config: LitConfig): void { - try { - fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2)); - } catch (error) { - console.error("Error saving config:", error); - } - } - - async verifyConfig(_config: LitConfig): Promise { - // Add verification logic here - // For example, check if the PKP is still valid - // Return false if verification fails - return true; - } -} From b1bc4bafb1e99d495ab71f5612d6b3e6368ed19b Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:07:33 -0500 Subject: [PATCH 03/10] Delete packages/plugin-lit/src/actions/sendSol.ts --- packages/plugin-lit/src/actions/sendSol.ts | 345 --------------------- 1 file changed, 345 deletions(-) delete mode 100644 packages/plugin-lit/src/actions/sendSol.ts diff --git a/packages/plugin-lit/src/actions/sendSol.ts b/packages/plugin-lit/src/actions/sendSol.ts deleted file mode 100644 index ae13f88cf79..00000000000 --- a/packages/plugin-lit/src/actions/sendSol.ts +++ /dev/null @@ -1,345 +0,0 @@ -import { - Action, - HandlerCallback, - IAgentRuntime, - Memory, - State, - Content, -} from "@elizaos/core"; -import { LitNodeClient } from "@lit-protocol/lit-node-client"; -import { LIT_ABILITY } from "@lit-protocol/constants"; -import { LitActionResource } from "@lit-protocol/auth-helpers"; -import { EthWalletProvider } from "@lit-protocol/lit-auth-client"; -import { api } from "@lit-protocol/wrapped-keys"; -import * as web3 from "@solana/web3.js"; -import * as ethers from "ethers"; -import { LitConfigManager } from "../config/configManager"; -import { composeContext, generateObject, ModelClass } from "@elizaos/core"; -import { z } from "zod"; -import { sendUsdcSchema } from "./sendUSDC"; - -const { importPrivateKey, signTransactionWithEncryptedKey } = api; - -interface LitState { - nodeClient: LitNodeClient; - evmWallet?: ethers.Wallet; - pkp?: { - publicKey: string; - ethAddress: string; - solanaAddress?: string; - }; - capacityCredit?: { - tokenId: string; - }; - wrappedKeyId?: string; -} - -// Add template for content extraction -const sendSolTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. - -Example response: -\`\`\`json -{ - "amount": "0.1", - "to": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU" -} -\`\`\` - -{{recentMessages}} - -Given the recent messages, extract the following information about the SOL transfer: -- amount (the amount of SOL to send) -- to (the destination address) - -Respond with a JSON markdown block containing only the extracted values.`; - -// Define the schema type -const sendSolSchema = z.object({ - amount: z.string().nullable(), - to: z.string().nullable() -}); - -// Add type guard function -function isSendSolContent(content: Content): content is SendSolContent { - return ( - (typeof content.amount === "string" || content.amount === null) && - (typeof content.to === "string" || content.to === null) - ); -} - -interface SendSolContent extends Content { - amount: string | null; - to: string | null; -} - -export const sendSol: Action = { - name: "SEND_SOL", - description: "Sends SOL to an address using Lit Wrapped Keys", - similes: [ - "send sol", - "send * sol to *", - "send solana", - "send * SOL to *", - "transfer * sol to *", - "transfer * SOL to *", - ], - validate: async (_runtime: IAgentRuntime) => true, - handler: async ( - runtime: IAgentRuntime, - message: Memory, - state: State, - _options: Record, - callback?: HandlerCallback - ): Promise => { - console.log("SEND_SOL handler started"); - try { - // Initialize or update state - let currentState: State; - if (!state) { - currentState = (await runtime.composeState(message)) as State; - } else { - currentState = await runtime.updateRecentMessageState(state); - } - - // Compose context and generate content - const sendSolContext = composeContext({ - state: currentState, - template: sendSolTemplate, - }); - - // Generate content with the schema - // Generate content with the schema - const content = await generateObject({ - runtime, - context: sendSolContext, - schema: sendSolSchema as any, - modelClass: ModelClass.LARGE, - }); - - const sendSolContent = content.object as SendSolContent; - - // Validate content - if (!isSendSolContent(sendSolContent)) { - console.error("Invalid content for SEND_SOL action."); - callback?.({ - text: "Unable to process SOL transfer request. Invalid content provided.", - content: { error: "Invalid send SOL content" } - }); - return false; - } - - if (!sendSolContent.amount) { - console.log("Amount is not provided, skipping transfer"); - callback?.({ text: "The amount must be provided" }); - return false; - } - - if (!sendSolContent.to) { - console.log("Destination address is not provided, skipping transfer"); - callback?.({ text: "The destination address must be provided" }); - return false; - } - - // Validate Lit environment - const litState = (state.lit || {}) as LitState; - if (!litState.nodeClient || !litState.pkp || !litState.evmWallet) { - throw new Error("Lit environment not fully initialized"); - } - - // Initialize Solana connection - const connection = new web3.Connection( - web3.clusterApiUrl("mainnet-beta"), - "confirmed" - ); - - // Get the private key from config - const configManager = new LitConfigManager(); - const config = configManager.loadConfig(); - if (!config?.solanaWalletPrivateKey) { - throw new Error("Solana wallet private key not found in config"); - } - - // Check for existing wrapped key ID in config - if (config?.wrappedKeyId) { - litState.wrappedKeyId = config.wrappedKeyId; - } else { - // Only create new wrapped key if one doesn't exist - const ethersSigner = litState.evmWallet; - - console.log("Getting PKP Session Sigs for wrapped key creation..."); - const pkpSessionSigs = await litState.nodeClient.getPkpSessionSigs({ - pkpPublicKey: litState.pkp.publicKey, - authMethods: [ - await EthWalletProvider.authenticate({ - signer: ethersSigner, - litNodeClient: litState.nodeClient, - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), - }), - ], - resourceAbilityRequests: [ - { - resource: new LitActionResource("*"), - ability: LIT_ABILITY.LitActionExecution, - }, - ], - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), - }); - console.log("✅ Successfully created PKP Session Sigs:", !!pkpSessionSigs); - - // Decode and import the private key - const privateKeyBytes = Buffer.from(config.solanaWalletPrivateKey, 'base64'); - const keypair = web3.Keypair.fromSecretKey(privateKeyBytes); - - console.log("Importing Solana private key as wrapped key..."); - const importResponse = await importPrivateKey({ - pkpSessionSigs, - litNodeClient: litState.nodeClient, - privateKey: Buffer.from(keypair.secretKey).toString('hex'), - publicKey: keypair.publicKey.toBase58(), - keyType: "ed25519", - memo: "Solana PKP Wallet", - }); - console.log("✅ Successfully imported Solana private key as wrapped key:", importResponse.id); - - // Save wrapped key ID to both state and config - litState.wrappedKeyId = importResponse.id; - configManager.saveConfig({ - ...config, - wrappedKeyId: importResponse.id, - }); - } - - // Fund the wallet with 2 devnet SOL if needed - if (!litState.pkp.solanaAddress) { - throw new Error("Solana address not found in PKP"); - } - const fromPubkey = new web3.PublicKey(litState.pkp.solanaAddress); - const toPubkey = new web3.PublicKey(sendSolContent.to); - - console.log("Sending from wallet address:", fromPubkey.toString()); - - // Check current balance - const balance = await connection.getBalance(fromPubkey); - console.log("Current wallet balance:", balance / web3.LAMPORTS_PER_SOL, "SOL"); - - /* DEVNET ONLY: Uncomment this block when using devnet - if (balance === 0) { - try { - console.log("Wallet empty, requesting 2 SOL airdrop..."); - const airdropSignature = await connection.requestAirdrop( - fromPubkey, - 2 * web3.LAMPORTS_PER_SOL - ); - const latestBlockhash = await connection.getLatestBlockhash(); - await connection.confirmTransaction({ - signature: airdropSignature, - blockhash: latestBlockhash.blockhash, - lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, - }); - console.log("Airdrop successful"); - } catch (error) { - console.error("Airdrop failed:", error); - throw new Error("Failed to fund wallet with devnet SOL"); - } - } else { - console.log("Wallet already has sufficient balance, skipping airdrop"); - } - */ - - // Mainnet balance check (comment this out if using devnet airdrop logic) - if (balance === 0) { - throw new Error("Wallet has insufficient balance"); - } - - const transaction = new web3.Transaction().add( - web3.SystemProgram.transfer({ - fromPubkey, - toPubkey, - lamports: web3.LAMPORTS_PER_SOL * Number.parseFloat(sendSolContent.amount), - }) - ); - - // Get recent blockhash - const { blockhash } = await connection.getLatestBlockhash(); - transaction.recentBlockhash = blockhash; - transaction.feePayer = fromPubkey; - - // Get session sigs for transaction signing - const pkpSessionSigs = await litState.nodeClient.getPkpSessionSigs({ - pkpPublicKey: litState.pkp.publicKey, - authMethods: [ - await EthWalletProvider.authenticate({ - signer: litState.evmWallet, - litNodeClient: litState.nodeClient, - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), - }), - ], - resourceAbilityRequests: [ - { - resource: new LitActionResource("*"), - ability: LIT_ABILITY.LitActionExecution, - }, - ], - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), - }); - - // Sign and send transaction - // For devnet: change 'mainnet-beta' to 'devnet' - if (!litState.wrappedKeyId) { - throw new Error("Wrapped key ID not found"); - } - const signedTx = await signTransactionWithEncryptedKey({ - pkpSessionSigs, - network: "solana", - id: litState.wrappedKeyId, - unsignedTransaction: { - chain: 'mainnet-beta', - serializedTransaction: transaction.serialize({ - requireAllSignatures: false, - }).toString('base64') - }, - broadcast: true, - litNodeClient: litState.nodeClient, - }); - - callback?.({ - text: `Successfully sent ${sendSolContent.amount} SOL to ${sendSolContent.to}. Transaction signature: ${signedTx}`, - content: { - success: true, - signature: signedTx, - amount: sendSolContent.amount, - to: sendSolContent.to, - }, - }); - - return true; - } catch (error) { - console.error("Error in sendSol:", error); - callback?.({ - text: `Failed to send SOL: ${error instanceof Error ? error.message : "Unknown error" - }`, - content: { - success: false, - error: error instanceof Error ? error.message : "Unknown error", - }, - }); - return false; - } - }, - examples: [ - [ - { - user: "{{user1}}", - content: { - text: "Send 0.1 SOL to 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", - }, - }, - { - user: "{{user2}}", - content: { - text: "Successfully sent SOL", - }, - }, - ], - ], -}; \ No newline at end of file From 732d97a633d9937994e3e149fcec3e39e25119d1 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:07:47 -0500 Subject: [PATCH 04/10] Delete packages/plugin-lit/src/actions/sendEth.ts --- packages/plugin-lit/src/actions/sendEth.ts | 331 --------------------- 1 file changed, 331 deletions(-) delete mode 100644 packages/plugin-lit/src/actions/sendEth.ts diff --git a/packages/plugin-lit/src/actions/sendEth.ts b/packages/plugin-lit/src/actions/sendEth.ts deleted file mode 100644 index e6f13d915b9..00000000000 --- a/packages/plugin-lit/src/actions/sendEth.ts +++ /dev/null @@ -1,331 +0,0 @@ -import { - Action, - HandlerCallback, - IAgentRuntime, - Memory, - State, - ModelClass, - composeContext, - generateObject, - Content - } from "@elizaos/core"; -import { ethers } from "ethers"; -import { LitNodeClient } from "@lit-protocol/lit-node-client"; -import { LIT_RPC, LIT_ABILITY } from "@lit-protocol/constants"; - import { - LitPKPResource, - createSiweMessageWithRecaps, - generateAuthSig, - LitActionResource, - AuthSig, -} from "@lit-protocol/auth-helpers"; -import { z } from "zod"; - -interface LitState { - nodeClient: LitNodeClient; - evmWallet?: ethers.Wallet; - pkp?: { - publicKey: string; - ethAddress: string; - }; - capacityCredit?: { - tokenId: string; - }; -} - -// Add template for content extraction -const sendEthTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. - -Example response: -\`\`\`json -{ - "amount": "0.01", - "to": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" -} -\`\`\` - -{{recentMessages}} - -Given the recent messages, extract the following information about the ETH transfer: -- amount (the amount of ETH to send) -- to (the destination address) - -Respond with a JSON markdown block containing only the extracted values.`; - -// Define the schema type -const sendEthSchema = z.object({ - amount: z.string().nullable(), - to: z.string().nullable() -}); - -// Add type guard function -function isSendEthContent(content: Content): content is SendEthContent { - return ( - (typeof content.amount === "string" || content.amount === null) && - (typeof content.to === "string" || content.to === null) - ); -} - -interface SendEthContent extends Content { - amount: string | null; - to: string | null; -} - -export const sendEth: Action = { - name: "SEND_ETH", - description: "Sends ETH to an address on Sepolia using PKP wallet", - similes: [ - "send eth", - "send * eth to *", - "send ethereum", - "send * ETH to *", - "transfer * eth to *", - "transfer * ETH to *", - ], - validate: async (_runtime: IAgentRuntime) => true, - handler: async ( - runtime: IAgentRuntime, - message: Memory, - state: State, - _options: Record, - callback?: HandlerCallback - ): Promise => { - console.log("SEND_ETH handler started"); - try { - // Initialize or update state - let currentState: State; - if (!state) { - currentState = (await runtime.composeState(message)) as State; - } else { - currentState = await runtime.updateRecentMessageState(state); - } - // Compose context and generate content - const sendEthContext = composeContext({ - state: currentState, - template: sendEthTemplate, - }); - - // Generate content with the schema - const content = await generateObject({ - runtime, - context: sendEthContext, - schema: sendEthSchema as any, - modelClass: ModelClass.LARGE, - }); - - const sendEthContent = content.object as SendEthContent; - - // Validate content - if (!isSendEthContent(sendEthContent)) { - console.error("Invalid content for SEND_ETH action."); - callback?.({ - text: "Unable to process ETH transfer request. Invalid content provided.", - content: { error: "Invalid send ETH content" } - }); - return false; - } - - if (!sendEthContent.amount) { - console.log("Amount is not provided, skipping transfer"); - callback?.({ text: "The amount must be provided" }); - return false; - } - - if (!sendEthContent.to) { - console.log("Destination address is not provided, skipping transfer"); - callback?.({ text: "The destination address must be provided" }); - return false; - } - - // Validate amount format - const cleanedAmount = sendEthContent.amount.replace(/[^\d.]/g, ''); - const parsedAmount = Number.parseFloat(cleanedAmount); - if (Number.isNaN(parsedAmount) || parsedAmount <= 0) { - throw new Error(`Invalid amount value: ${sendEthContent.amount}`); - } - - // Validate address format - if (!/^0x[a-fA-F0-9]{40}$/.test(sendEthContent.to)) { - throw new Error(`Invalid Ethereum address: ${sendEthContent.to}`); - } - - // Validate Lit environment - const litState = (state.lit || {}) as LitState; - if ( - !litState.nodeClient || - !litState.pkp || - !litState.evmWallet || - !litState.capacityCredit?.tokenId - ) { - throw new Error( - "Lit environment not fully initialized - missing nodeClient, pkp, evmWallet, or capacityCredit" - ); - } - - // Get RPC URL from runtime settings - const rpcUrl = runtime.getSetting("EVM_RPC_URL"); - if (!rpcUrl) { - throw new Error("No RPC URL provided"); - } - - const provider = new ethers.providers.JsonRpcProvider(rpcUrl); - - // Create transaction - const nonce = await provider.getTransactionCount(litState.pkp.ethAddress); - const gasPrice = await provider.getGasPrice(); - const gasLimit = 30000; - - const unsignedTx = { - to: sendEthContent.to, - value: ethers.utils.parseEther(sendEthContent.amount), - chainId: 11155111, // Sepolia chainId - nonce: nonce, - gasPrice: gasPrice, - gasLimit: gasLimit, - }; - - const fundingWallet = new ethers.Wallet( - runtime.getSetting("FUNDING_PRIVATE_KEY"), - new ethers.providers.JsonRpcProvider(LIT_RPC.CHRONICLE_YELLOWSTONE) - ); - - const { capacityDelegationAuthSig } = - await litState.nodeClient.createCapacityDelegationAuthSig({ - dAppOwnerWallet: fundingWallet, - capacityTokenId: litState.capacityCredit.tokenId, - delegateeAddresses: [litState.pkp.ethAddress], - uses: "1", - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), // 10 minutes - }); - - // Get session signatures with capacity delegation - console.log("Generating session signatures with capacity delegation..."); - const sessionSigs = await litState.nodeClient.getSessionSigs({ - pkpPublicKey: litState.pkp.publicKey, - chain: "sepolia", - capabilityAuthSigs: [capacityDelegationAuthSig], - expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours - resourceAbilityRequests: [ - { - resource: new LitPKPResource("*"), - ability: LIT_ABILITY.PKPSigning, - }, - { - resource: new LitActionResource("*"), - ability: LIT_ABILITY.LitActionExecution, - }, - ], - authNeededCallback: async ({ - resourceAbilityRequests, - expiration, - uri, - }) => { - if (!uri || !expiration || !resourceAbilityRequests) { - throw new Error("Missing required parameters for auth callback"); - } - const toSign = await createSiweMessageWithRecaps({ - uri, - expiration, - resources: resourceAbilityRequests, - walletAddress: litState.evmWallet.address, - nonce: await litState.nodeClient.getLatestBlockhash(), - litNodeClient: litState.nodeClient, - }); - - return await generateAuthSig({ - signer: litState.evmWallet, - toSign, - }); - }, - }); - console.log("Session signatures generated"); - - console.log("Signing transaction..."); - const sig = await litState.nodeClient.pkpSign({ - pubKey: litState.pkp.publicKey, - toSign: ethers.utils.arrayify( - ethers.utils.keccak256(ethers.utils.serializeTransaction(unsignedTx)) - ), - sessionSigs, - }); - - // Combine signature with transaction - const signature = { - r: `0x${sig.r}`, - s: `0x${sig.s}`, - v: sig.recid === 0 ? 27 : 28, - }; - - // Verify signature by recovering the address - const msgHash = ethers.utils.keccak256( - ethers.utils.serializeTransaction(unsignedTx) - ); - const recoveredAddress = ethers.utils.recoverAddress(msgHash, signature); - - // If address doesn't match, try the other v value - if ( - recoveredAddress.toLowerCase() !== litState.pkp.ethAddress.toLowerCase() - ) { - signature.v = signature.v === 27 ? 28 : 27; // Toggle between 27 and 28 - const altRecoveredAddress = ethers.utils.recoverAddress( - msgHash, - signature - ); - - if ( - altRecoveredAddress.toLowerCase() !== - litState.pkp.ethAddress.toLowerCase() - ) { - throw new Error("Failed to recover correct address from signature"); - } - } - - const signedTx = ethers.utils.serializeTransaction(unsignedTx, signature); - - // Send transaction - console.log("Sending transaction..."); - const sentTx = await provider.sendTransaction(signedTx); - await sentTx.wait(); - - callback?.({ - text: `Successfully sent ${sendEthContent.amount} ETH to ${sendEthContent.to}. Transaction hash: ${sentTx.hash}`, - content: { - success: true, - hash: sentTx.hash, - amount: sendEthContent.amount, - to: sendEthContent.to, - }, - }); - - return true; - } catch (error) { - console.error("Error in sendEth:", error); - callback?.({ - text: `Failed to send ETH: ${ - error instanceof Error ? error.message : "Unknown error" - }`, - content: { - success: false, - error: error instanceof Error ? error.message : "Unknown error", - }, - }); - return false; - } - }, - examples: [ - [ - { - user: "{{user1}}", - content: { - text: "Send 0.01 ETH to 0x742d35Cc6634C0532925a3b844Bc454e4438f44e", - }, - }, - { - user: "{{user2}}", - content: { - text: "Successfully sent ETH", - }, - }, - ], - ], -}; From 95e1f96d2d90c7a844f2ba855ab2748636cace7a Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:07:53 -0500 Subject: [PATCH 05/10] Delete packages/plugin-lit/src/actions/sendUSDC.ts --- packages/plugin-lit/src/actions/sendUSDC.ts | 207 -------------------- 1 file changed, 207 deletions(-) delete mode 100644 packages/plugin-lit/src/actions/sendUSDC.ts diff --git a/packages/plugin-lit/src/actions/sendUSDC.ts b/packages/plugin-lit/src/actions/sendUSDC.ts deleted file mode 100644 index 36bbeb846bd..00000000000 --- a/packages/plugin-lit/src/actions/sendUSDC.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { Action, HandlerCallback, IAgentRuntime, Memory, State } from "@elizaos/core"; -import { ethers } from "ethers"; -import { LitNodeClient } from "@lit-protocol/lit-node-client"; -import { LIT_RPC, LIT_ABILITY } from "@lit-protocol/constants"; -import { LitPKPResource, createSiweMessageWithRecaps, generateAuthSig, LitActionResource } from "@lit-protocol/auth-helpers"; -import { z } from "zod"; -import { ModelClass, composeContext, generateObject, Content } from "@elizaos/core"; - -const USDC_CONTRACT_ADDRESS = "0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8"; // Sepolia USDC (AAVE) -const USDC_ABI = ["function transfer(address to, uint256 amount) returns (bool)"]; - -interface LitState { - nodeClient: LitNodeClient; - evmWallet?: ethers.Wallet; - pkp?: { - publicKey: string; - ethAddress: string; - }; - capacityCredit?: { - tokenId: string; - }; -} - -// Add template for content extraction -const sendUsdcTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. - -Example response: -\`\`\`json -{ - "amount": "10", - "to": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" -} -\`\`\` - -{{recentMessages}} - -Given the recent messages, extract the following information about the USDC transfer: -- amount (the amount of USDC to send) -- to (the destination address) - -Respond with a JSON markdown block containing only the extracted values.`; - -// Define the schema type -export const sendUsdcSchema = z.object({ - amount: z.string().nullable(), - to: z.string().nullable() -}); - -// Add type guard function -function isSendUsdcContent(content: Content): content is SendUsdcContent { - return ( - (typeof content.amount === "string" || content.amount === null) && - (typeof content.to === "string" || content.to === null) - ); -} - -interface SendUsdcContent extends Content { - amount: string | null; - to: string | null; -} - -export const sendUSDC: Action = { - name: "SEND_USDC", - description: "Sends USDC to an address on Sepolia using PKP wallet", - similes: ["send usdc", "send * usdc to *", "transfer * usdc to *"], - validate: async (_runtime: IAgentRuntime) => true, - handler: async ( - runtime: IAgentRuntime, - message: Memory, - state: State, - _options: Record, - callback?: HandlerCallback - ): Promise => { - try { - // Initialize or update state - let currentState: State; - if (!state) { - currentState = (await runtime.composeState(message)) as State; - } else { - currentState = await runtime.updateRecentMessageState(state); - } - - // Compose context and generate content - const sendUsdcContext = composeContext({ - state: currentState, - template: sendUsdcTemplate, - }); - - // Generate content with the schema - const content = await generateObject({ - runtime, - context: sendUsdcContext, - schema: sendUsdcSchema as any, - modelClass: ModelClass.LARGE, - }); - - const sendUsdcContent = content.object as SendUsdcContent; - - // Validate content - if (!isSendUsdcContent(sendUsdcContent)) { - console.error("Invalid content for SEND_USDC action."); - callback?.({ - text: "Unable to process USDC transfer request. Invalid content provided.", - content: { error: "Invalid send USDC content" } - }); - return false; - } - - if (!sendUsdcContent.amount) { - console.log("Amount is not provided, skipping transfer"); - callback?.({ text: "The amount must be provided" }); - return false; - } - - if (!sendUsdcContent.to) { - console.log("Destination address is not provided, skipping transfer"); - callback?.({ text: "The destination address must be provided" }); - return false; - } - - const amount = sendUsdcContent.amount; - const to = sendUsdcContent.to; - const litState = (state.lit || {}) as LitState; - if (!litState.nodeClient || !litState.pkp || !litState.evmWallet || !litState.capacityCredit?.tokenId) { - throw new Error("Lit environment not fully initialized"); - } - - const provider = new ethers.providers.JsonRpcProvider(runtime.getSetting("EVM_RPC_URL")); - const usdcContract = new ethers.Contract(USDC_CONTRACT_ADDRESS, USDC_ABI, provider); - const decimals = 6; // USDC has 6 decimals - const value = ethers.utils.parseUnits(amount, decimals); - - const unsignedTx = await usdcContract.populateTransaction.transfer(to, value); - unsignedTx.nonce = await provider.getTransactionCount(litState.pkp.ethAddress); - unsignedTx.gasPrice = await provider.getGasPrice(); - unsignedTx.gasLimit = ethers.BigNumber.from(100000); - unsignedTx.chainId = 11155111; // Sepolia - - const fundingWallet = new ethers.Wallet( - runtime.getSetting("FUNDING_PRIVATE_KEY"), - new ethers.providers.JsonRpcProvider(LIT_RPC.CHRONICLE_YELLOWSTONE) - ); - - const { capacityDelegationAuthSig } = await litState.nodeClient.createCapacityDelegationAuthSig({ - dAppOwnerWallet: fundingWallet, - capacityTokenId: litState.capacityCredit.tokenId, - delegateeAddresses: [litState.pkp.ethAddress], - uses: "1", - expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), - }); - - const sessionSigs = await litState.nodeClient.getSessionSigs({ - pkpPublicKey: litState.pkp.publicKey, - chain: "sepolia", - capabilityAuthSigs: [capacityDelegationAuthSig], - expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), - resourceAbilityRequests: [ - { resource: new LitPKPResource("*"), ability: LIT_ABILITY.PKPSigning }, - { resource: new LitActionResource("*"), ability: LIT_ABILITY.LitActionExecution }, - ], - authNeededCallback: async ({ resourceAbilityRequests, expiration, uri }) => { - if (!uri || !expiration || !resourceAbilityRequests) { - throw new Error("Missing required parameters for auth callback"); - } - const toSign = await createSiweMessageWithRecaps({ - uri, - expiration, - resources: resourceAbilityRequests, - walletAddress: litState.evmWallet.address, - nonce: await litState.nodeClient.getLatestBlockhash(), - litNodeClient: litState.nodeClient, - }); - return await generateAuthSig({ signer: litState.evmWallet, toSign }); - }, - }); - - const sig = await litState.nodeClient.pkpSign({ - pubKey: litState.pkp.publicKey, - toSign: ethers.utils.arrayify(ethers.utils.keccak256(ethers.utils.serializeTransaction(unsignedTx))), - sessionSigs, - }); - - const signature = { r: `0x${sig.r}`, s: `0x${sig.s}`, v: sig.recid === 0 ? 27 : 28 }; - const signedTx = ethers.utils.serializeTransaction(unsignedTx, signature); - const sentTx = await provider.sendTransaction(signedTx); - await sentTx.wait(); - - callback?.({ - text: `Successfully sent ${amount} USDC to ${to}. Transaction hash: ${sentTx.hash}`, - content: { success: true, hash: sentTx.hash, amount, to }, - }); - return true; - - } catch (error) { - console.error("Error in sendUSDC:", error); - callback?.({ - text: `Failed to send USDC: ${error instanceof Error ? error.message : "Unknown error"}`, - content: { success: false, error: error instanceof Error ? error.message : "Unknown error" }, - }); - return false; - } - }, - examples: [[ - { user: "{{user1}}", content: { text: "Send 10 USDC to 0x742d35Cc6634C0532925a3b844Bc454e4438f44e" }}, - { user: "{{user2}}", content: { text: "Successfully sent USDC" }} - ]], -}; \ No newline at end of file From 3bddc2d1d76fbe8d12b58f166b3ff84609f0ba74 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:08:20 -0500 Subject: [PATCH 06/10] Delete packages/plugin-lit/src/actions/index.ts --- packages/plugin-lit/src/actions/index.ts | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 packages/plugin-lit/src/actions/index.ts diff --git a/packages/plugin-lit/src/actions/index.ts b/packages/plugin-lit/src/actions/index.ts deleted file mode 100644 index e9a499ae97b..00000000000 --- a/packages/plugin-lit/src/actions/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// export { swapTokens } from "./swapTokens"; -export { sendEth } from "./sendEth"; -export { sendUSDC } from "./sendUSDC"; -export { sendSol } from "./sendSol"; From 1fb201d251e77643f4f8010e8f68bfbebce03aa3 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:09:33 -0500 Subject: [PATCH 07/10] Delete packages/plugin-lit/src/types directory --- packages/plugin-lit/src/types/index.ts | 43 -------------------------- 1 file changed, 43 deletions(-) delete mode 100644 packages/plugin-lit/src/types/index.ts diff --git a/packages/plugin-lit/src/types/index.ts b/packages/plugin-lit/src/types/index.ts deleted file mode 100644 index 22c7522873c..00000000000 --- a/packages/plugin-lit/src/types/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { LitNodeClient } from "@lit-protocol/lit-node-client"; -import { PKPEthersWallet } from "@lit-protocol/pkp-ethers"; - -export interface PKPWallet { - ethWallet: PKPEthersWallet; - // solWallet?: any; // TODO: Add Solana wallet type - tokenId: string; - publicKey: string; - ethAddress: string; -} - -export interface LitConfig { - network: "cayenne" | "datilDev" | "datilTest" | "datil"; - debug?: boolean; - minNodeCount?: number; -} - -export interface AuthMethod { - authMethodType: number; - accessToken: string; -} - -export interface AuthSig { - sig: string; - derivedVia: string; - signedMessage: string; - address: string; -} - -export interface SessionSigs { - [key: string]: AuthSig; -} - -export interface LitClientContext { - litNodeClient: LitNodeClient; - sessionSigs?: SessionSigs; - chain: "ethereum" | "solana"; -} - -export interface PKPWalletResponse { - publicKey: string; - ethAddress: string; -} From 60e25895f095e5b7005ebae8cd284eebe0d6ce8c Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:10:01 -0500 Subject: [PATCH 08/10] Delete packages/plugin-lit/pkp-setup.md --- packages/plugin-lit/pkp-setup.md | 109 ------------------------------- 1 file changed, 109 deletions(-) delete mode 100644 packages/plugin-lit/pkp-setup.md diff --git a/packages/plugin-lit/pkp-setup.md b/packages/plugin-lit/pkp-setup.md deleted file mode 100644 index c5d4b6023bc..00000000000 --- a/packages/plugin-lit/pkp-setup.md +++ /dev/null @@ -1,109 +0,0 @@ -# PKP Setup Guide for @plugin-lit - -## Overview -This guide explains the Programmable Key Pair (PKP) setup process for @plugin-lit and the configuration file structure. - -## Automatic PKP Creation - -The PKP creation in @plugin-lit is automatic. The process is handled by the `litProvider` during initialization, which: - -1. Checks for existing configuration -2. If no PKP exists, automatically: - - Creates a new EVM wallet - - Generates a Solana wallet - - Mints a new PKP - - Mints a capacity credit NFT - - Saves all configurations to `lit-config.json` - -## Configuration File Structure - -The `lit-config.json` file is automatically created with the following structure: - -```json -{ -"pkp": { -"tokenId": "0xca60...", // The PKP token ID -"publicKey": "04b756...", // The PKP public key -"ethAddress": "0xB2D4...", // The Ethereum address -"solanaAddress": "HzunQ..." // The Solana address -}, -"network": "Chain ID 175188", // The network identifier -"timestamp": 1735839217558, // Creation timestamp -"evmWalletPrivateKey": "0x710...", // EVM wallet private key -"solanaWalletPrivateKey": "Wz0...", // Solana wallet private key (base64) -"capacityCredit": { -"tokenId": "87622" // Capacity credit NFT token ID -}, -"wrappedKeyId": "0b410..." // Wrapped key identifier -} -``` - - -### Configuration Fields Explained - -#### PKP Section -- `tokenId`: Unique identifier for the PKP NFT -- `publicKey`: PKP's public key -- `ethAddress`: Generated Ethereum address -- `solanaAddress`: Generated Solana address - -#### Other Fields -- `network`: Identifies the blockchain network -- `timestamp`: Creation timestamp -- `evmWalletPrivateKey`: Private key for EVM transactions -- `solanaWalletPrivateKey`: Private key for Solana transactions (base64 encoded) -- `capacityCredit.tokenId`: Used for rate limiting and usage tracking -- `wrappedKeyId`: Used for secure key management with Lit Protocol - -## Security Considerations - -The `lit-config.json` file contains sensitive information. Important security measures: - -1. Add to `.gitignore` -2. Never share or expose the file -3. Maintain secure backups -4. Store in a safe location - -## Required Environment Variables - -Set these environment variables for proper PKP creation: - -```env -FUNDING_PRIVATE_KEY= # Private key for funding operations -RPC_URL= # RPC endpoint for blockchain interactions -``` - - -## Optional Manual Configuration - -There are two ways to use an existing PKP instead of automatic creation: - -1. Set the environment variable: -```env -LIT_PKP_PUBLIC_KEY= # Your existing PKP public key -``` - -2. Copy an existing `lit-config.json` file: - - Simply copy your existing `lit-config.json` file into your project's root directory - - The plugin will detect and use this configuration instead of creating a new one - - Ensure the copied configuration file contains all required fields - - This is useful for maintaining the same PKP across multiple environments or projects - -> Note: When copying an existing configuration, make sure to maintain proper security practices and never commit the file to version control. - - -## Verification Steps - -Verify your setup by checking: - -1. `lit-config.json` exists in your project -2. PKP configuration is valid -3. Capacity credit NFT is allocated - -The plugin handles ongoing PKP rotation and management automatically based on the configuration. - -## Support - -For additional support or questions: -- Visit the [Lit Protocol Documentation](https://developer.litprotocol.com/) -- Join the [Lit Protocol Discord](https://discord.com/invite/lit) \ No newline at end of file From 56186e82b49386ea6bd2cf1152152a4e5b7ba9c2 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:10:39 -0500 Subject: [PATCH 09/10] Delete packages/plugin-lit/.npmignore --- packages/plugin-lit/.npmignore | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 packages/plugin-lit/.npmignore diff --git a/packages/plugin-lit/.npmignore b/packages/plugin-lit/.npmignore deleted file mode 100644 index 0468b4b3648..00000000000 --- a/packages/plugin-lit/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -* - -!dist/** -!package.json -!readme.md -!tsup.config.ts From e193644b45736ab10fb806267c0c1bcab87b3b03 Mon Sep 17 00:00:00 2001 From: Robert Mads Christensen <61755754+madschristensen99@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:12:50 -0500 Subject: [PATCH 10/10] Update README.md --- packages/plugin-lit/README.md | 124 ---------------------------------- 1 file changed, 124 deletions(-) diff --git a/packages/plugin-lit/README.md b/packages/plugin-lit/README.md index 88bacf4ad08..c273a11f779 100644 --- a/packages/plugin-lit/README.md +++ b/packages/plugin-lit/README.md @@ -13,39 +13,6 @@ A plugin that integrates Lit Protocol functionality into the elizaOS runtime env ## Installation -A comprehensive blockchain interaction plugin for the Eliza Agent Stack, powered by Lit Protocol's Programmable Key Pairs (PKPs). This plugin enables autonomous agents to perform secure cross-chain transactions through decentralized key management and threshold cryptography. - -## Overview - -The Lit Protocol plugin provides: -- Dual-chain wallet management (EVM + Solana) -- Secure transaction signing and execution -- Capacity credit management -- Automated PKP lifecycle management -- Security evaluations for transactions - -## Features - -- **Wallet Management** - - Automated PKP creation and management - - Dual-chain support (EVM + Solana) - - Secure key storage and rotation - - Capacity credit allocation - -- **Transaction Support** - - ETH transfers - - USDC transfers - - SOL transfers - - Transaction security validation - -- **Security Features** - - Transaction amount limits - - Security evaluations - - PKP validation - - Session management - - Capacity credit monitoring - -## Installation ```bash npm install @elizaos/plugin-lit ``` @@ -179,94 +146,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -======= -## Configuration - -Required environment variables: -```env -FUNDING_PRIVATE_KEY= # Private key for funding operations -EVM_RPC_URL= # RPC endpoint for blockchain interactions -LIT_PKP_PUBLIC_KEY= # (Optional) Existing PKP public key -``` - -## Important: Wallet Funding - -Before executing any transactions, you must fund the generated Lit wallet address with the necessary assets (ETH, SOL, or USDC). The plugin will create a new PKP wallet address if one isn't provided, and this address will need to hold sufficient funds to: -1. Cover the amount being transferred -2. Pay for transaction fees (gas fees on EVM chains, transaction fees on Solana) - -You can view your PKP wallet address after initializing the plugin using the configuration file (`lit-config.json`). - -## Usage - -### Basic Setup -```typescript -import { litPlugin } from '@elizaos/plugin-lit'; - -// Register the plugin -runtime.registerPlugin(litPlugin); -``` - -### Sending ETH -```typescript -// Send ETH transaction -await runtime.executeAction('SEND_ETH', { - text: "Send 0.01 ETH to 0x742d35Cc6634C0532925a3b844Bc454e4438f44e" -}); -``` - -### Sending SOL -```typescript -// Send SOL transaction -await runtime.executeAction('SEND_SOL', { - text: "Send 0.1 SOL to 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU" -}); -``` - -### Sending USDC -```typescript -// Send USDC transaction -await runtime.executeAction('SEND_USDC', { - text: "Send 10 USDC to 0x742d35Cc6634C0532925a3b844Bc454e4438f44e" -}); -``` - -## Security - -The plugin implements multiple security layers: -- Transaction amount limits -- Automated security evaluations -- PKP validation checks -- Session-based authentication -- Capacity credit management -- Automatic key rotation - -## Architecture - -The plugin consists of several key components: - -- **Providers** - - `litProvider`: Manages PKP creation and Lit Protocol integration - - `pkpPermissionsProvider`: Handles PKP permissions and auth methods - -- **Actions** - - `sendEth`: ETH transfer functionality - - `sendSol`: SOL transfer functionality - - `sendUSDC`: USDC transfer functionality - -## Configuration Management - -The plugin uses a local configuration file (`lit-config.json`) to store: -- PKP details -- Network configuration -- Wallet information -- Capacity credits -- Session data - -## Contributing - -Contributions are welcome! Please see our [Contributing Guide](../CONTRIBUTING.md) for details. - -## License - -MIT