diff --git a/local-tests/test.ts b/local-tests/test.ts index 8b79e961cc..716d9c3e83 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -86,11 +86,13 @@ import { testExecuteJsBroadcastAndCollect } from './tests/testExecuteJsBroadcast import { testEthereumSignMessageGeneratedKey } from './tests/testEthereumSignMessageGeneratedKey'; import { testEthereumBroadcastTransactionGeneratedKey } from './tests/testEthereumBroadcastTransactionGeneratedKey'; import { testEthereumSignMessageWrappedKey } from './tests/testEthereumSignMessageWrappedKey'; +import { testFailEthereumSignTransactionWrappedKeyInvalidDecryption } from './tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption'; // import { testFailWrappedKeySigningTimeout } from './tests/testFailWrappedKeySigningTimeout'; import { testEthereumSignTransactionWrappedKey } from './tests/testEthereumSignTransactionWrappedKey'; import { testFailEthereumSignTransactionWrappedKeyWithInvalidParam } from './tests/testFailEthereumSignTransactionWrappedKeyWithInvalidParam'; import { testFailEthereumSignTransactionWrappedKeyWithMissingParam } from './tests/testFailEthereumSignTransactionWrappedKeyWithMissingParam'; import { testEthereumBroadcastTransactionWrappedKey } from './tests/testEthereumBroadcastTransactionWrappedKey'; +import { testEthereumBroadcastWrappedKeyWithFetchGasParams } from './tests/testEthereumBroadcastWrappedKeyWithFetchGasParams'; import { testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds } from './tests/testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds'; import { testImportWrappedKey } from './tests/testImportWrappedKey'; import { testGenerateWrappedKey } from './tests/testGenerateWrappedKey'; @@ -110,6 +112,7 @@ import { testExportWrappedKey } from './tests/testExportWrappedKey'; await devEnv.init(); const wrappedKeysTests = { + testFailEthereumSignTransactionWrappedKeyInvalidDecryption, testEthereumSignMessageGeneratedKey, testEthereumBroadcastTransactionGeneratedKey, // testRemoveDecryptFailingOutsideLitAction, @@ -118,6 +121,7 @@ import { testExportWrappedKey } from './tests/testExportWrappedKey'; testFailEthereumSignTransactionWrappedKeyWithInvalidParam, testFailEthereumSignTransactionWrappedKeyWithMissingParam, testEthereumBroadcastTransactionWrappedKey, + testEthereumBroadcastWrappedKeyWithFetchGasParams, testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds, testImportWrappedKey, testGenerateWrappedKey, diff --git a/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts b/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts new file mode 100644 index 0000000000..05aa7d84ac --- /dev/null +++ b/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts @@ -0,0 +1,88 @@ +import { log } from '@lit-protocol/misc'; +import { ethers } from 'ethers'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { + importPrivateKey, + EthereumLitTransaction, + signTransactionWithEthereumEncryptedKeyLitAction, + signTransactionWithEncryptedKey, +} from '@lit-protocol/wrapped-keys'; +import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; + +/** + * Test Commands: + * ✅ NETWORK=cayenne yarn test:local --filter=testEthereumBroadcastWrappedKeyWithFetchGasParams + * ❌ NETWORK=manzano yarn test:local --filter=testEthereumBroadcastWrappedKeyWithFetchGasParams Fails with Error: Error: There should be exactly 1 element in the capabilities array but there are: 2 + * ❌ NETWORK=localchain yarn test:local --filter=testEthereumBroadcastWrappedKeyWithFetchGasParams + */ +export const testEthereumBroadcastWrappedKeyWithFetchGasParams = async ( + devEnv: TinnyEnvironment +) => { + const alice = await devEnv.createRandomPerson(); + + const pkpSessionSigs = await getPkpSessionSigs( + devEnv, + alice, + null, + new Date(Date.now() + 1000 * 60 * 10).toISOString() + ); // 10 mins expiry + + console.log(pkpSessionSigs); + + const wrappedKeysWallet = ethers.Wallet.createRandom(); + const wrappedKeysWalletPrivateKey = wrappedKeysWallet.privateKey; + + const wrappedKeysWalletAddress = wrappedKeysWallet.address; + console.log(`Sending funds to ${wrappedKeysWalletAddress}`); + await devEnv.getFunds(wrappedKeysWallet.address, '0.005'); + + const pkpAddress = await importPrivateKey({ + pkpSessionSigs, + privateKey: wrappedKeysWalletPrivateKey, + litNodeClient: devEnv.litNodeClient, + }); + + const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; + if (pkpAddress !== alicePkpAddress) { + throw new Error( + `Received address: ${pkpAddress} doesn't match Alice's PKP address: ${alicePkpAddress}` + ); + } + + const pkpSessionSigsSigning = await getPkpSessionSigs( + devEnv, + alice, + null, + new Date(Date.now() + 1000 * 60 * 10).toISOString() + ); // 10 mins expiry + + console.log(pkpSessionSigsSigning); + + const unsignedTransaction: EthereumLitTransaction = { + toAddress: alice.wallet.address, + value: '0.0001', // in ethers (Lit tokens) + chainId: 175177, // Chronicle + dataHex: ethers.utils.hexlify( + ethers.utils.toUtf8Bytes('Test transaction from Alice to bob') + ), + chain: 'chronicleTestnet', + }; + + const signedTx = await signTransactionWithEncryptedKey({ + pkpSessionSigs: pkpSessionSigsSigning, + litActionCode: signTransactionWithEthereumEncryptedKeyLitAction, + unsignedTransaction, + broadcast: true, + litNodeClient: devEnv.litNodeClient, + }); + + console.log('signedTx'); + console.log(signedTx); + + // TODO!: Convert hex signedTx to UTF-8 and assert that it contains "Test transaction from Alice to bob" + if (!ethers.utils.isHexString(signedTx)) { + throw new Error(`signedTx isn't hex: ${signedTx}`); + } + + log('✅ testEthereumBroadcastWrappedKeyWithDefaultGasParams'); +}; diff --git a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts new file mode 100644 index 0000000000..9c31c206e3 --- /dev/null +++ b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts @@ -0,0 +1,86 @@ +import { log } from '@lit-protocol/misc'; +import { ethers } from 'ethers'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { + EthereumLitTransaction, + signTransactionWithEthereumEncryptedKeyLitAction, +} from '@lit-protocol/wrapped-keys'; +import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; +import { getPkpAccessControlCondition } from 'packages/wrapped-keys/src/lib/utils'; +import { encryptString } from '@lit-protocol/encryption'; +import { LIT_PREFIX } from 'packages/wrapped-keys/src/lib/constants'; + +/** + * Test Commands: + * ✅ NETWORK=cayenne yarn test:local --filter=testFailEthereumSignTransactionWrappedKeyInvalidDecryption + * ✅ NETWORK=manzano yarn test:local --filter=testFailEthereumSignTransactionWrappedKeyInvalidDecryption + * ✅ NETWORK=localchain yarn test:local --filter=testFailEthereumSignTransactionWrappedKeyInvalidDecryption + */ +export const testFailEthereumSignTransactionWrappedKeyInvalidDecryption = + async (devEnv: TinnyEnvironment) => { + const alice = await devEnv.createRandomPerson(); + const privateKey = ethers.Wallet.createRandom().privateKey; + const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; + const decryptionAccessControlConditions = + getPkpAccessControlCondition(alicePkpAddress); + const { ciphertext, dataToEncryptHash } = await encryptString( + { + accessControlConditions: decryptionAccessControlConditions, + dataToEncrypt: LIT_PREFIX + privateKey, + }, + devEnv.litNodeClient + ); + + const bob = await devEnv.createRandomPerson(); + const pkpSessionSigsSigning = await getPkpSessionSigs( + devEnv, + bob, + null, + new Date(Date.now() + 1000 * 60 * 10).toISOString() + ); // 10 mins expiry + console.log(pkpSessionSigsSigning); + + const unsignedTransaction: EthereumLitTransaction = { + toAddress: alice.wallet.address, + value: '0.0001', // in ethers (Lit tokens) + chainId: 175177, // Chronicle + gasPrice: '50', + gasLimit: 21000, + dataHex: ethers.utils.hexlify( + ethers.utils.toUtf8Bytes('Test transaction from Alice to bob') + ), + chain: 'chronicleTestnet', + }; + + try { + const _res = await devEnv.litNodeClient.executeJs({ + sessionSigs: pkpSessionSigsSigning, + code: signTransactionWithEthereumEncryptedKeyLitAction, + jsParams: { + ciphertext, + dataToEncryptHash, + unsignedTransaction, + accessControlConditions: decryptionAccessControlConditions, + }, + }); + } catch (e: any) { + console.log('❌ THIS IS EXPECTED: ', e); + console.log(e.message); + + // TODO!: Add appropriate assertions based on the above error message + // if ( + // e.message.includes( + // 'Error executing the Signing Lit Action: Error: When signing transaction- processing response' + // ) && + // e.message.includes('insufficient FPE funds for gas * price + value') + // ) { + // console.log( + // '✅ testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds is expected to have an error' + // ); + // } else { + // throw e; + // } + } + + log('✅ testFailEthereumSignTransactionWrappedKeyInvalidDecryption'); + }; diff --git a/packages/constants/src/lib/constants/autogen_internal.ts b/packages/constants/src/lib/constants/autogen_internal.ts index adc3430812..5ccccb56b0 100644 --- a/packages/constants/src/lib/constants/autogen_internal.ts +++ b/packages/constants/src/lib/constants/autogen_internal.ts @@ -3,11 +3,10 @@ export const INTERNAL_DEV = [ 'https://167.114.17.201:443', 'https://64.131.85.108:443', 'https://167.114.17.202:443', - 'https://167.114.17.205:443', + 'https://64.131.85.106:443', 'https://167.114.17.203:443', 'https://108.62.0.105:443', 'https://167.114.17.204:443', - 'https://64.131.85.106:443', ]; export const INTERNAL_MIN_NODE_COUNT = 2; @@ -20,11 +19,10 @@ export const INTERNAL_DEFAULT_CONFIG = { 'https://167.114.17.201:443', 'https://64.131.85.108:443', 'https://167.114.17.202:443', - 'https://167.114.17.205:443', + 'https://64.131.85.106:443', 'https://167.114.17.203:443', 'https://108.62.0.105:443', 'https://167.114.17.204:443', - 'https://64.131.85.106:443', ], litNetwork: 'internalDev', connectTimeout: 20000, diff --git a/packages/wrapped-keys/src/lib/litActions.ts b/packages/wrapped-keys/src/lib/litActions.ts index 813c48df00..328ab5b635 100644 --- a/packages/wrapped-keys/src/lib/litActions.ts +++ b/packages/wrapped-keys/src/lib/litActions.ts @@ -1,185 +1,250 @@ -export const generatePrivateKeyLitAction = ` -const LIT_PREFIX = 'lit_'; - -(async () => { - const resp = await Lit.Actions.runOnce( - { waitForResponse: true, name: 'encryptedPrivateKey' }, - async () => { - const wallet = ethers.Wallet.createRandom(); - const privateKey = LIT_PREFIX + wallet.privateKey.toString(); - let utf8Encode = new TextEncoder(); - const to_encrypt = utf8Encode.encode(privateKey); - - const { ciphertext, dataToEncryptHash } = await Lit.Actions.encrypt({ - accessControlConditions, - to_encrypt, - }); - return JSON.stringify({ ciphertext, dataToEncryptHash, publicKey: wallet.publicKey }); - } - ); +// @ts-nocheck - // // TODO: Remove the below which is only for demonstrating the error - // const { ciphertext, dataToEncryptHash } = JSON.parse(resp); - // const decrypted = await Lit.Actions.decryptAndCombine({ - // accessControlConditions, - // ciphertext, - // dataToEncryptHash, - // authSig: null, - // chain: 'ethereum', - // }); - - // // TODO: Remove the below which is only for demonstrating the error - // console.log('accessControlConditions: ', accessControlConditions); - // console.log('ciphertext: ', ciphertext); - // console.log('dataToEncryptHash: ', dataToEncryptHash); - // console.log('decrypted: ', decrypted); +const _generatePrivateKeyLitAction = async () => { + const LIT_PREFIX = 'lit_'; - Lit.Actions.setResponse({ - response: resp, - }); -})(); -`; - -export const signTransactionWithEthereumEncryptedKeyLitAction = ` -const DEFAULT_GAS_LIMIT = 21000; -const DEFAULT_GAS_PRICE = '50'; // in gwei -const LIT_PREFIX = 'lit_'; - -(async () => { - // TODO!: Remove ALL the console.log statements - console.log('unsignedTransaction'); - console.log(unsignedTransaction); - - if (!unsignedTransaction.toAddress) { - Lit.Actions.setResponse({ response: 'Error: Missing required field: toAddress' }); - return; - } + const resp = await Lit.Actions.runOnce( + { waitForResponse: true, name: 'encryptedPrivateKey' }, + async () => { + const wallet = ethers.Wallet.createRandom(); + const privateKey = LIT_PREFIX + wallet.privateKey.toString(); + let utf8Encode = new TextEncoder(); + const to_encrypt = utf8Encode.encode(privateKey); - if (!unsignedTransaction.chain) { - Lit.Actions.setResponse({ response: 'Error: Missing required field: chain' }); - return; - } - - if (!unsignedTransaction.value) { - Lit.Actions.setResponse({ response: 'Error: Missing required field: value' }); - return; - } - - if (!unsignedTransaction.chainId) { - Lit.Actions.setResponse({ response: 'Error: Missing required field: chainId' }); - return; - } - - const decryptedPrivateKey = await Lit.Actions.decryptToSingleNode({ + const { ciphertext, dataToEncryptHash } = await Lit.Actions.encrypt({ accessControlConditions, + to_encrypt, + }); + return JSON.stringify({ ciphertext, dataToEncryptHash, - chain: 'ethereum', - authSig: null, - }); - - console.log('decryptedPrivateKey'); - console.log(decryptedPrivateKey); - - if (!decryptedPrivateKey) { // Exit the nodes which don't have the decryptedData - return; + publicKey: wallet.publicKey, + }); } + ); - const privateKey = decryptedPrivateKey.startsWith(LIT_PREFIX) ? decryptedPrivateKey.slice(LIT_PREFIX.length) : decryptedPrivateKey; - const wallet = new ethers.Wallet(privateKey); + Lit.Actions.setResponse({ + response: resp, + }); +}; - const gasPrice = unsignedTransaction.gasPrice ? unsignedTransaction.gasPrice : DEFAULT_GAS_PRICE; - const gasLimit = unsignedTransaction.gasLimit ? unsignedTransaction.gasLimit : DEFAULT_GAS_LIMIT; +const _signTransactionWithEthereumEncryptedKeyLitAction = async () => { + const LIT_PREFIX = 'lit_'; - console.log('unsignedTransaction.chain', unsignedTransaction.chain); - console.log('pkpAddress', pkpAddress); - const nonce = await Lit.Actions.getLatestNonce({ address: wallet.address, chain: unsignedTransaction.chain }); - console.log('nonce'); - console.log(nonce); - - const tx = { - to: unsignedTransaction.toAddress, - value: ethers.utils.parseEther(unsignedTransaction.value), - chainId: unsignedTransaction.chainId, - gasPrice: ethers.utils.parseUnits(gasPrice, 'gwei'), - gasLimit, - data: unsignedTransaction.dataHex, - nonce, - }; + // TODO!: Remove ALL the console.log statements + console.log('unsignedTransaction'); + console.log(unsignedTransaction); - console.log('tx'); - console.log(tx); - - try { - const signedTx = await wallet.signTransaction(tx); + if (!unsignedTransaction.toAddress) { + Lit.Actions.setResponse({ + response: 'Error: Missing required field: toAddress', + }); + return; + } - if (broadcast) { - const rpcUrl = await Lit.Actions.getRpcUrl({ chain: unsignedTransaction.chain }); - const provider = new ethers.providers.JsonRpcProvider(rpcUrl); + if (!unsignedTransaction.chain) { + Lit.Actions.setResponse({ + response: 'Error: Missing required field: chain', + }); + return; + } - const transactionResponse = await provider.sendTransaction(signedTx); + if (!unsignedTransaction.value) { + Lit.Actions.setResponse({ + response: 'Error: Missing required field: value', + }); + return; + } - Lit.Actions.setResponse({ response: transactionResponse.hash }); - } else { - Lit.Actions.setResponse({ response: signedTx }); - } + if (!unsignedTransaction.chainId) { + Lit.Actions.setResponse({ + response: 'Error: Missing required field: chainId', + }); + return; + } + + let decryptedPrivateKey; + try { + decryptedPrivateKey = await Lit.Actions.decryptToSingleNode({ + accessControlConditions, + ciphertext, + dataToEncryptHash, + chain: 'ethereum', + authSig: null, + }); + } catch (err) { + const errorMessage = + 'Error: When decrypting to a single node- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + return; + } + + console.log('decryptedPrivateKey'); + console.log(decryptedPrivateKey); + + if (!decryptedPrivateKey) { + // Exit the nodes which don't have the decryptedData + return; + } + + const privateKey = decryptedPrivateKey.startsWith(LIT_PREFIX) + ? decryptedPrivateKey.slice(LIT_PREFIX.length) + : decryptedPrivateKey; + const wallet = new ethers.Wallet(privateKey); + + console.log('unsignedTransaction.chain', unsignedTransaction.chain); + console.log('pkpAddress', pkpAddress); + + let nonce; + try { + nonce = await Lit.Actions.getLatestNonce({ + address: wallet.address, + chain: unsignedTransaction.chain, + }); + console.log('nonce'); + console.log(nonce); + } catch (err) { + const errorMessage = 'Error: Unable to get the nonce- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + return; + } + + const tx = { + to: unsignedTransaction.toAddress, + from: wallet.address, + value: ethers.utils.hexlify( + ethers.utils.parseEther(unsignedTransaction.value) + ), + chainId: unsignedTransaction.chainId, + data: unsignedTransaction.dataHex, + nonce, + }; + + let provider; + try { + const rpcUrl = await Lit.Actions.getRpcUrl({ + chain: unsignedTransaction.chain, + }); + provider = new ethers.providers.JsonRpcProvider(rpcUrl); + } catch (err) { + const errorMessage = + `Error: Getting the rpc for the chain: ${unsignedTransaction.chain}- ` + + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + return; + } + + if (unsignedTransaction.gasPrice) { + tx.gasPrice = ethers.utils.parseUnits(unsignedTransaction.gasPrice, 'gwei'); + } else { + try { + tx.gasPrice = await provider.getGasPrice(); } catch (err) { - const errorMessage = 'Error: When signing transaction- ' + err.message; - Lit.Actions.setResponse({ response: errorMessage }); + const errorMessage = 'Error: When getting gas price- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + return; } -})(); -`; - -export const signMessageWithEthereumEncryptedKeyLitAction = ` -const LIT_PREFIX = 'lit_'; - -(async () => { - // TODO!: Remove ALL the console.log statements - console.log('unsignedMessage'); - console.log(unsignedMessage); - - const decryptedPrivateKey = await Lit.Actions.decryptToSingleNode({ - accessControlConditions, - ciphertext, - dataToEncryptHash, - chain: 'ethereum', - authSig: null, - }); - - console.log('decryptedPrivateKey'); - console.log(decryptedPrivateKey); + } - if (!decryptedPrivateKey) { // Exit the nodes which don't have the decryptedData - return; + if (unsignedTransaction.gasLimit) { + tx.gasLimit = unsignedTransaction.gasLimit; + } else { + try { + tx.gasLimit = await provider.estimateGas(tx); + } catch (err) { + const errorMessage = 'Error: When estimating gas- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + return; } + } - const privateKey = decryptedPrivateKey.startsWith(LIT_PREFIX) ? decryptedPrivateKey.slice(LIT_PREFIX.length) : decryptedPrivateKey; - const wallet = new ethers.Wallet(privateKey); - - try { - const signature = await wallet.signMessage(unsignedMessage); - console.log('signature'); - console.log(signature); + console.log('tx'); + console.log(tx); - const recoveredAddress = ethers.utils.verifyMessage(unsignedMessage, signature); - console.log('recoveredAddress'); - console.log(recoveredAddress); + try { + const signedTx = await wallet.signTransaction(tx); - if (recoveredAddress !== wallet.address) { - Lit.Actions.setResponse({ response: "Error: Recovered address doesn't match the wallet address" }); - return; - } + if (broadcast) { + const transactionResponse = await provider.sendTransaction(signedTx); - Lit.Actions.setResponse({ response: signature }); - } catch (err) { - const errorMessage = 'Error: When signing message- ' + err.message; - Lit.Actions.setResponse({ response: errorMessage }); + Lit.Actions.setResponse({ response: transactionResponse.hash }); + } else { + Lit.Actions.setResponse({ response: signedTx }); + } + } catch (err) { + const errorMessage = 'Error: When signing transaction- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + } +}; + +const _signMessageWithEthereumEncryptedKeyLitAction = async () => { + const LIT_PREFIX = 'lit_'; + + // TODO!: Remove ALL the console.log statements + console.log('unsignedMessage'); + console.log(unsignedMessage); + + let decryptedPrivateKey; + try { + decryptedPrivateKey = await Lit.Actions.decryptToSingleNode({ + accessControlConditions, + ciphertext, + dataToEncryptHash, + chain: 'ethereum', + authSig: null, + }); + } catch (err) { + const errorMessage = + 'Error: When decrypting to a single node- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + return; + } + + console.log('decryptedPrivateKey'); + console.log(decryptedPrivateKey); + + if (!decryptedPrivateKey) { + // Exit the nodes which don't have the decryptedData + return; + } + + const privateKey = decryptedPrivateKey.startsWith(LIT_PREFIX) + ? decryptedPrivateKey.slice(LIT_PREFIX.length) + : decryptedPrivateKey; + const wallet = new ethers.Wallet(privateKey); + + try { + const signature = await wallet.signMessage(unsignedMessage); + console.log('signature'); + console.log(signature); + + const recoveredAddress = ethers.utils.verifyMessage( + unsignedMessage, + signature + ); + console.log('recoveredAddress'); + console.log(recoveredAddress); + + if (recoveredAddress !== wallet.address) { + Lit.Actions.setResponse({ + response: "Error: Recovered address doesn't match the wallet address", + }); + return; } -})(); -`; - -// export const signingTimeoutEncryptedKeyLitAction = ` -// (async () => { -// new Promise(resolve => setTimeout(resolve, 40000)); // Sleep for 40 seconds -// })(); -// `; + + Lit.Actions.setResponse({ response: signature }); + } catch (err) { + const errorMessage = 'Error: When signing message- ' + err.message; + Lit.Actions.setResponse({ response: errorMessage }); + } +}; + +const generatePrivateKeyLitAction = `(${_generatePrivateKeyLitAction.toString})();`; +const signTransactionWithEthereumEncryptedKeyLitAction = `(${_signTransactionWithEthereumEncryptedKeyLitAction.toString()})();`; +const signMessageWithEthereumEncryptedKeyLitAction = `(${_signMessageWithEthereumEncryptedKeyLitAction.toString()})();`; + +export { + generatePrivateKeyLitAction, + signMessageWithEthereumEncryptedKeyLitAction, + signTransactionWithEthereumEncryptedKeyLitAction, +};