diff --git a/README.md b/README.md index 452f2d2023..5f0be3b400 100644 --- a/README.md +++ b/README.md @@ -50,41 +50,39 @@ yarn add @lit-protocol/lit-node-client -Package | Category | Download ---- | --- | --- -| [@lit-protocol/lit-node-client-nodejs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client-nodejs) | ![lit-node-client-nodejs](https://img.shields.io/badge/-nodejs-2E8B57 "lit-node-client-nodejs") | -| [@lit-protocol/lit-node-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client) | ![lit-node-client](https://img.shields.io/badge/-universal-8A6496 "lit-node-client") | - +| Package | Category | Download | +| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [@lit-protocol/lit-node-client-nodejs](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client-nodejs) | ![lit-node-client-nodejs](https://img.shields.io/badge/-nodejs-2E8B57 'lit-node-client-nodejs') | | +| [@lit-protocol/lit-node-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/lit-node-client) | ![lit-node-client](https://img.shields.io/badge/-universal-8A6496 'lit-node-client') | | If you're a tech-savvy user and wish to utilize only specific submodules that our main module relies upon, you can find individual packages listed below. This way, you can import only the necessary packages that cater to your specific use case:: - -Package | Category | Download ---- | --- | --- -| [@lit-protocol/access-control-conditions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions) | ![access-control-conditions](https://img.shields.io/badge/-universal-8A6496 "access-control-conditions") | -| [@lit-protocol/auth-helpers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-helpers) | ![auth-helpers](https://img.shields.io/badge/-universal-8A6496 "auth-helpers") | -| [@lit-protocol/bls-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/bls-sdk) | ![bls-sdk](https://img.shields.io/badge/-universal-8A6496 "bls-sdk") | -| [@lit-protocol/constants](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/constants) | ![constants](https://img.shields.io/badge/-universal-8A6496 "constants") | -| [@lit-protocol/contracts-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/contracts-sdk) | ![contracts-sdk](https://img.shields.io/badge/-universal-8A6496 "contracts-sdk") | -| [@lit-protocol/core](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/core) | ![core](https://img.shields.io/badge/-universal-8A6496 "core") | -| [@lit-protocol/crypto](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/crypto) | ![crypto](https://img.shields.io/badge/-universal-8A6496 "crypto") | -| [@lit-protocol/ecdsa-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/ecdsa-sdk) | ![ecdsa-sdk](https://img.shields.io/badge/-universal-8A6496 "ecdsa-sdk") | -| [@lit-protocol/encryption](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/encryption) | ![encryption](https://img.shields.io/badge/-universal-8A6496 "encryption") | -| [@lit-protocol/logger](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/logger) | ![logger](https://img.shields.io/badge/-universal-8A6496 "logger") | -| [@lit-protocol/misc](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc) | ![misc](https://img.shields.io/badge/-universal-8A6496 "misc") | -| [@lit-protocol/nacl](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/nacl) | ![nacl](https://img.shields.io/badge/-universal-8A6496 "nacl") | -| [@lit-protocol/pkp-base](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-base) | ![pkp-base](https://img.shields.io/badge/-universal-8A6496 "pkp-base") | -| [@lit-protocol/pkp-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-client) | ![pkp-client](https://img.shields.io/badge/-universal-8A6496 "pkp-client") | -| [@lit-protocol/pkp-cosmos](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-cosmos) | ![pkp-cosmos](https://img.shields.io/badge/-universal-8A6496 "pkp-cosmos") | -| [@lit-protocol/pkp-ethers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-ethers) | ![pkp-ethers](https://img.shields.io/badge/-universal-8A6496 "pkp-ethers") | -| [@lit-protocol/pkp-sui](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-sui) | ![pkp-sui](https://img.shields.io/badge/-universal-8A6496 "pkp-sui") | -| [@lit-protocol/pkp-walletconnect](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-walletconnect) | ![pkp-walletconnect](https://img.shields.io/badge/-universal-8A6496 "pkp-walletconnect") | -| [@lit-protocol/sev-snp-utils-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/sev-snp-utils-sdk) | ![sev-snp-utils-sdk](https://img.shields.io/badge/-universal-8A6496 "sev-snp-utils-sdk") | -| [@lit-protocol/types](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/types) | ![types](https://img.shields.io/badge/-universal-8A6496 "types") | -| [@lit-protocol/uint8arrays](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/uint8arrays) | ![uint8arrays](https://img.shields.io/badge/-universal-8A6496 "uint8arrays") | -| [@lit-protocol/wrapped-keys](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wrapped-keys) | ![wrapped-keys](https://img.shields.io/badge/-universal-8A6496 "wrapped-keys") | -| [@lit-protocol/auth-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-browser) | ![auth-browser](https://img.shields.io/badge/-browser-E98869 "auth-browser") | -| [@lit-protocol/misc-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc-browser) | ![misc-browser](https://img.shields.io/badge/-browser-E98869 "misc-browser") | +| Package | Category | Download | +| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [@lit-protocol/access-control-conditions](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/access-control-conditions) | ![access-control-conditions](https://img.shields.io/badge/-universal-8A6496 'access-control-conditions') | | +| [@lit-protocol/auth-helpers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-helpers) | ![auth-helpers](https://img.shields.io/badge/-universal-8A6496 'auth-helpers') | | +| [@lit-protocol/bls-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/bls-sdk) | ![bls-sdk](https://img.shields.io/badge/-universal-8A6496 'bls-sdk') | | +| [@lit-protocol/constants](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/constants) | ![constants](https://img.shields.io/badge/-universal-8A6496 'constants') | | +| [@lit-protocol/contracts-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/contracts-sdk) | ![contracts-sdk](https://img.shields.io/badge/-universal-8A6496 'contracts-sdk') | | +| [@lit-protocol/core](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/core) | ![core](https://img.shields.io/badge/-universal-8A6496 'core') | | +| [@lit-protocol/crypto](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/crypto) | ![crypto](https://img.shields.io/badge/-universal-8A6496 'crypto') | | +| [@lit-protocol/ecdsa-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/ecdsa-sdk) | ![ecdsa-sdk](https://img.shields.io/badge/-universal-8A6496 'ecdsa-sdk') | | +| [@lit-protocol/encryption](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/encryption) | ![encryption](https://img.shields.io/badge/-universal-8A6496 'encryption') | | +| [@lit-protocol/logger](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/logger) | ![logger](https://img.shields.io/badge/-universal-8A6496 'logger') | | +| [@lit-protocol/misc](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc) | ![misc](https://img.shields.io/badge/-universal-8A6496 'misc') | | +| [@lit-protocol/nacl](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/nacl) | ![nacl](https://img.shields.io/badge/-universal-8A6496 'nacl') | | +| [@lit-protocol/pkp-base](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-base) | ![pkp-base](https://img.shields.io/badge/-universal-8A6496 'pkp-base') | | +| [@lit-protocol/pkp-client](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-client) | ![pkp-client](https://img.shields.io/badge/-universal-8A6496 'pkp-client') | | +| [@lit-protocol/pkp-cosmos](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-cosmos) | ![pkp-cosmos](https://img.shields.io/badge/-universal-8A6496 'pkp-cosmos') | | +| [@lit-protocol/pkp-ethers](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-ethers) | ![pkp-ethers](https://img.shields.io/badge/-universal-8A6496 'pkp-ethers') | | +| [@lit-protocol/pkp-sui](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-sui) | ![pkp-sui](https://img.shields.io/badge/-universal-8A6496 'pkp-sui') | | +| [@lit-protocol/pkp-walletconnect](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/pkp-walletconnect) | ![pkp-walletconnect](https://img.shields.io/badge/-universal-8A6496 'pkp-walletconnect') | | +| [@lit-protocol/sev-snp-utils-sdk](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/sev-snp-utils-sdk) | ![sev-snp-utils-sdk](https://img.shields.io/badge/-universal-8A6496 'sev-snp-utils-sdk') | | +| [@lit-protocol/types](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/types) | ![types](https://img.shields.io/badge/-universal-8A6496 'types') | | +| [@lit-protocol/uint8arrays](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/uint8arrays) | ![uint8arrays](https://img.shields.io/badge/-universal-8A6496 'uint8arrays') | | +| [@lit-protocol/wrapped-keys](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/wrapped-keys) | ![wrapped-keys](https://img.shields.io/badge/-universal-8A6496 'wrapped-keys') | | +| [@lit-protocol/auth-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/auth-browser) | ![auth-browser](https://img.shields.io/badge/-browser-E98869 'auth-browser') | | +| [@lit-protocol/misc-browser](https://github.com/LIT-Protocol/js-sdk/tree/master/packages/misc-browser) | ![misc-browser](https://img.shields.io/badge/-browser-E98869 'misc-browser') | | diff --git a/lerna.json b/lerna.json index 40bcbb86c5..0e4d62ecdf 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useNx": true, "useWorkspaces": true, - "version": "6.0.3-wrapped-keys.beta.3" + "version": "6.0.3-wrapped-keys.beta.4" } diff --git a/local-tests/test.ts b/local-tests/test.ts index f2f2ead32f..ce614fe364 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -85,7 +85,6 @@ import { testExecuteJsBroadcastAndCollect } from './tests/testExecuteJsBroadcast import { testEthereumSignMessageGeneratedKey } from './tests/testEthereumSignMessageGeneratedKey'; import { testEthereumBroadcastTransactionGeneratedKey } from './tests/testEthereumBroadcastTransactionGeneratedKey'; -import { testCustomignMessageWrappedKey } from './tests/testCustomSignMessageWrappedKey'; import { testEthereumSignMessageWrappedKey } from './tests/testEthereumSignMessageWrappedKey'; import { testFailEthereumSignTransactionWrappedKeyInvalidDecryption } from './tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption'; import { testEthereumSignTransactionWrappedKey } from './tests/testEthereumSignTransactionWrappedKey'; @@ -97,14 +96,12 @@ import { testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds } from import { testImportWrappedKey } from './tests/testImportWrappedKey'; import { testGenerateEthereumWrappedKey } from './tests/testGenerateEthereumWrappedKey'; import { testGenerateSolanaWrappedKey } from './tests/testGenerateSolanaWrappedKey'; -import { testCustomGenerateWrappedKey } from './tests/testCustomGenerateWrappedKey'; import { testFailImportWrappedKeysWithSamePkp } from './tests/testFailImportWrappedKeysWithSamePkp'; import { testFailImportWrappedKeysWithSamePrivateKey } from './tests/testFailImportWrappedKeysWithSamePrivateKey'; import { testFailImportWrappedKeysWithEoaSessionSig } from './tests/testFailImportWrappedKeysWithEoaSessionSig'; import { testFailImportWrappedKeysWithMaxExpirySessionSig } from './tests/testFailImportWrappedKeysWithMaxExpirySessionSig'; import { testFailImportWrappedKeysWithInvalidSessionSig } from './tests/testFailImportWrappedKeysWithInvalidSessionSig'; import { testFailImportWrappedKeysWithExpiredSessionSig } from './tests/testFailImportWrappedKeysWithExpiredSessionSig'; -import { testFailCustomGenerateKeyWithBothIpfsAndCode } from './tests/testFailCustomGenerateKeyWithBothIpfsAndCode'; import { testExportWrappedKey } from './tests/testExportWrappedKey'; import { testSignMessageWithSolanaEncryptedKey } from './tests/testSignMessageWithSolanaEncryptedKey'; import { testSignTransactionWithSolanaEncryptedKey } from './tests/testSignTransactionWithSolanaEncryptedKey'; @@ -120,7 +117,6 @@ import { testSignTransactionWithSolanaEncryptedKey } from './tests/testSignTrans testEthereumSignMessageGeneratedKey, testEthereumBroadcastTransactionGeneratedKey, testEthereumSignMessageWrappedKey, - testCustomignMessageWrappedKey, testEthereumSignTransactionWrappedKey, testEthereumBroadcastTransactionWrappedKey, testEthereumBroadcastWrappedKeyWithFetchGasParams, @@ -128,7 +124,6 @@ import { testSignTransactionWithSolanaEncryptedKey } from './tests/testSignTrans // -- generate wrapped keys testGenerateEthereumWrappedKey, testGenerateSolanaWrappedKey, - testCustomGenerateWrappedKey, // -- import wrapped keys testImportWrappedKey, @@ -146,7 +141,6 @@ import { testSignTransactionWithSolanaEncryptedKey } from './tests/testSignTrans testFailEthereumSignTransactionWrappedKeyWithInvalidParam, testFailEthereumSignTransactionWrappedKeyInvalidDecryption, testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds, - testFailCustomGenerateKeyWithBothIpfsAndCode, // -- import wrapped keys testFailImportWrappedKeysWithSamePkp, diff --git a/local-tests/tests/testCustomGenerateWrappedKey.ts b/local-tests/tests/testCustomGenerateWrappedKey.ts deleted file mode 100644 index 2588d146f8..0000000000 --- a/local-tests/tests/testCustomGenerateWrappedKey.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { log } from '@lit-protocol/misc'; -import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { customGeneratePrivateKey } from '@lit-protocol/wrapped-keys'; -import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { LIT_ACTION_CID_REPOSITORY } from 'packages/wrapped-keys/src/lib/constants'; - -const CUSTOM_LIT_ACTION_CODE = ` -(async () => { - const LIT_PREFIX = 'lit_'; - - 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, - }); - } - ); - - Lit.Actions.setResponse({ - response: resp, - }); -})(); -`; - -/** - * Test Commands: - * ✅ NETWORK=cayenne yarn test:local --filter=testCustomGenerateWrappedKey - * ✅ NETWORK=manzano yarn test:local --filter=testCustomGenerateWrappedKey - * ✅ NETWORK=localchain yarn test:local --filter=testCustomGenerateWrappedKey - */ -export const testCustomGenerateWrappedKey = async ( - devEnv: TinnyEnvironment -) => { - // Generate custom keys with IPFS CID - const alice = await devEnv.createRandomPerson(); - - const alicePkpSessionSigs = await getPkpSessionSigs( - devEnv, - alice, - null, - new Date(Date.now() + 1000 * 60 * 10).toISOString() - ); // 10 mins expiry - - const ipfsCustomPrivateKeys = await customGeneratePrivateKey({ - pkpSessionSigs: alicePkpSessionSigs, - litActionIpfsCid: - LIT_ACTION_CID_REPOSITORY.generateEncryptedSolanaPrivateKey, - litNodeClient: devEnv.litNodeClient, - }); - - console.log( - `IPFS CID generatedPublicKey: ${ipfsCustomPrivateKeys.generatedPublicKey}` - ); - - const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; - if (ipfsCustomPrivateKeys.pkpAddress !== alicePkpAddress) { - throw new Error( - `Received address: ${ipfsCustomPrivateKeys.pkpAddress} doesn't match Alice's PKP address: ${alicePkpAddress}` - ); - } - - // Generate custom keys with code - const bob = await devEnv.createRandomPerson(); - - const bobPkpSessionSigs = await getPkpSessionSigs( - devEnv, - bob, - null, - new Date(Date.now() + 1000 * 60 * 10).toISOString() - ); // 10 mins expiry - - const codeCustomPrivateKeys = await customGeneratePrivateKey({ - pkpSessionSigs: bobPkpSessionSigs, - litActionCode: CUSTOM_LIT_ACTION_CODE, - litNodeClient: devEnv.litNodeClient, - }); - - console.log( - `Code generatedPublicKey: ${codeCustomPrivateKeys.generatedPublicKey}` - ); - - const bobPkpAddress = bob.authMethodOwnedPkp.ethAddress; - if (codeCustomPrivateKeys.pkpAddress !== bobPkpAddress) { - throw new Error( - `Received address: ${codeCustomPrivateKeys.pkpAddress} doesn't match Bob's PKP address: ${bobPkpAddress}` - ); - } - - log('✅ testCustomGenerateWrappedKey'); -}; diff --git a/local-tests/tests/testCustomSignMessageWrappedKey.ts b/local-tests/tests/testCustomSignMessageWrappedKey.ts deleted file mode 100644 index c0fd13cf7d..0000000000 --- a/local-tests/tests/testCustomSignMessageWrappedKey.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { log } from '@lit-protocol/misc'; -import { ethers } from 'ethers'; -import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - customSignMessageWithEncryptedKey, - importPrivateKey, -} from '@lit-protocol/wrapped-keys'; -import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; - -const CUSTOM_LIT_ACTION_CODE = ` -(async () => { - const LIT_PREFIX = 'lit_'; - - 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; - } - - 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(messageToSign); - - const recoveredAddress = ethers.utils.verifyMessage( - messageToSign, - signature - ); - - if (recoveredAddress !== wallet.address) { - Lit.Actions.setResponse({ - response: "Error: Recovered address doesn't match the wallet address", - }); - return; - } - - Lit.Actions.setResponse({ response: signature }); - } catch (err) { - const errorMessage = 'Error: When signing message- ' + err.message; - Lit.Actions.setResponse({ response: errorMessage }); - } -})(); -`; - -/** - * Test Commands: - * ✅ NETWORK=cayenne yarn test:local --filter=testCustomignMessageWrappedKey - * ✅ NETWORK=manzano yarn test:local --filter=testCustomignMessageWrappedKey - * ✅ NETWORK=localchain yarn test:local --filter=testCustomignMessageWrappedKey - */ -export const testCustomignMessageWrappedKey = 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 privateKey = ethers.Wallet.createRandom().privateKey; - - const pkpAddress = await importPrivateKey({ - pkpSessionSigs, - privateKey, - 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 unsignedStringMessage = 'This is a test message'; - - const signature = await customSignMessageWithEncryptedKey({ - pkpSessionSigs: pkpSessionSigsSigning, - litActionCode: CUSTOM_LIT_ACTION_CODE, - messageToSign: unsignedStringMessage, - litNodeClient: devEnv.litNodeClient, - }); - - console.log('signature'); - console.log(signature); - - if (!ethers.utils.isHexString(signature)) { - throw new Error(`signature isn't hex: ${signature}`); - } - - log('✅ testCustomignMessageWrappedKey'); -}; diff --git a/local-tests/tests/testCustomSignTransactionWrappedKey.ts b/local-tests/tests/testCustomSignTransactionWrappedKey.ts deleted file mode 100644 index 3534df8665..0000000000 --- a/local-tests/tests/testCustomSignTransactionWrappedKey.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { log } from '@lit-protocol/misc'; -import { ethers } from 'ethers'; -import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signTransactionWithEncryptedKey, - EthereumLitTransaction, -} from '@lit-protocol/wrapped-keys'; -import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; - -const CUSTOM_LIT_ACTION_CODE = `(async () => { - const LIT_PREFIX = 'lit_'; - - let decryptedPrivateKey; - decryptedPrivateKey = await Lit.Actions.decryptToSingleNode({ - accessControlConditions, - ciphertext, - dataToEncryptHash, - chain: 'ethereum', - authSig: null, - }); - - 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); - - const nonce = await Lit.Actions.getLatestNonce({ - address: wallet.address, - chain: unsignedTransaction.chain, - }); - - const tx = { - to: unsignedTransaction.toAddress, - from: wallet.address, - value: ethers.utils.hexlify( - ethers.utils.parseEther(unsignedTransaction.value) - ), - chainId: unsignedTransaction.chainId, - data: unsignedTransaction.dataHex, - nonce, - gasPrice: ethers.utils.parseUnits(unsignedTransaction.gasPrice, 'gwei'), - gasLimit: unsignedTransaction.gasLimit, - }; - - const rpcUrl = await Lit.Actions.getRpcUrl({ - chain: unsignedTransaction.chain, - }); - const provider = new ethers.providers.JsonRpcProvider(rpcUrl); - - try { - const signedTx = await wallet.signTransaction(tx); - - if (broadcast) { - const transactionResponse = await provider.sendTransaction(signedTx); - - 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 }); - } -})(); -`; - -/** - * Test Commands: - * ✅ NETWORK=cayenne yarn test:local --filter=testEthereumSignTransactionWrappedKey - * ✅ NETWORK=manzano yarn test:local --filter=testEthereumSignTransactionWrappedKey - * ✅ NETWORK=localchain yarn test:local --filter=testEthereumSignTransactionWrappedKey - */ -export const testEthereumSignTransactionWrappedKey = 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 privateKey = ethers.Wallet.createRandom().privateKey; - - const pkpAddress = await importPrivateKey({ - pkpSessionSigs, - privateKey, - 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 - gasPrice: '50', - gasLimit: 21000, - dataHex: ethers.utils.hexlify( - ethers.utils.toUtf8Bytes('Test transaction from Alice to bob') - ), - chain: 'chronicleTestnet', - }; - - const signedTx = await signTransactionWithEncryptedKey({ - pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, - unsignedTransaction, - broadcast: false, - litNodeClient: devEnv.litNodeClient, - }); - - console.log('signedTx'); - console.log(signedTx); - - if (!ethers.utils.isHexString(signedTx)) { - throw new Error(`signedTx isn't hex: ${signedTx}`); - } - - log('✅ testEthereumSignTransactionWrappedKey'); -}; diff --git a/local-tests/tests/testEthereumBroadcastTransactionGeneratedKey.ts b/local-tests/tests/testEthereumBroadcastTransactionGeneratedKey.ts index 68d3135fa4..ef102b771c 100644 --- a/local-tests/tests/testEthereumBroadcastTransactionGeneratedKey.ts +++ b/local-tests/tests/testEthereumBroadcastTransactionGeneratedKey.ts @@ -1,13 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - signTransactionWithEncryptedKey, - EthereumLitTransaction, - generatePrivateKey, -} from '@lit-protocol/wrapped-keys'; +import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +const { signTransactionWithEncryptedKey, generatePrivateKey } = api; /** * Test Commands: @@ -31,7 +28,7 @@ export const testEthereumBroadcastTransactionGeneratedKey = async ( const { pkpAddress, generatedPublicKey } = await generatePrivateKey({ pkpSessionSigs, - network: NETWORK_EVM, + network: 'evm', litNodeClient: devEnv.litNodeClient, }); @@ -70,7 +67,7 @@ export const testEthereumBroadcastTransactionGeneratedKey = async ( const signedTx = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', unsignedTransaction, broadcast: true, litNodeClient: devEnv.litNodeClient, diff --git a/local-tests/tests/testEthereumBroadcastTransactionWrappedKey.ts b/local-tests/tests/testEthereumBroadcastTransactionWrappedKey.ts index 95f6d5dc77..7ce84fee50 100644 --- a/local-tests/tests/testEthereumBroadcastTransactionWrappedKey.ts +++ b/local-tests/tests/testEthereumBroadcastTransactionWrappedKey.ts @@ -1,13 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signTransactionWithEncryptedKey, - EthereumLitTransaction, -} from '@lit-protocol/wrapped-keys'; +import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: @@ -40,6 +37,8 @@ export const testEthereumBroadcastTransactionWrappedKey = async ( pkpSessionSigs, privateKey: wrappedKeysWalletPrivateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -72,7 +71,7 @@ export const testEthereumBroadcastTransactionWrappedKey = async ( const signedTx = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', unsignedTransaction, broadcast: true, litNodeClient: devEnv.litNodeClient, diff --git a/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts b/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts index 1657268a2d..26e0a1b5be 100644 --- a/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts +++ b/local-tests/tests/testEthereumBroadcastWrappedKeyWithFetchGasParams.ts @@ -1,13 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - EthereumLitTransaction, - signTransactionWithEncryptedKey, -} from '@lit-protocol/wrapped-keys'; +import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: @@ -40,6 +37,8 @@ export const testEthereumBroadcastWrappedKeyWithFetchGasParams = async ( pkpSessionSigs, privateKey: wrappedKeysWalletPrivateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -70,7 +69,7 @@ export const testEthereumBroadcastWrappedKeyWithFetchGasParams = async ( const signedTx = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', unsignedTransaction, broadcast: true, litNodeClient: devEnv.litNodeClient, diff --git a/local-tests/tests/testEthereumSignMessageGeneratedKey.ts b/local-tests/tests/testEthereumSignMessageGeneratedKey.ts index 8bf1f9e2e1..9d003b2ad5 100644 --- a/local-tests/tests/testEthereumSignMessageGeneratedKey.ts +++ b/local-tests/tests/testEthereumSignMessageGeneratedKey.ts @@ -1,12 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - generatePrivateKey, - signMessageWithEncryptedKey, -} from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +const { generatePrivateKey, signMessageWithEncryptedKey } = api; /** * Test Commands: @@ -30,7 +28,7 @@ export const testEthereumSignMessageGeneratedKey = async ( const { pkpAddress, generatedPublicKey } = await generatePrivateKey({ pkpSessionSigs, - network: NETWORK_EVM, + network: 'evm', litNodeClient: devEnv.litNodeClient, }); @@ -54,7 +52,7 @@ export const testEthereumSignMessageGeneratedKey = async ( const signature = await signMessageWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', messageToSign: unsignedStringMessage, litNodeClient: devEnv.litNodeClient, }); @@ -72,7 +70,7 @@ export const testEthereumSignMessageGeneratedKey = async ( const signatureBinary = await signMessageWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', messageToSign: unsignedBinaryMessage, litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testEthereumSignMessageWrappedKey.ts b/local-tests/tests/testEthereumSignMessageWrappedKey.ts index 9f77da06fa..b74ca6c865 100644 --- a/local-tests/tests/testEthereumSignMessageWrappedKey.ts +++ b/local-tests/tests/testEthereumSignMessageWrappedKey.ts @@ -1,12 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signMessageWithEncryptedKey, -} from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +const { importPrivateKey, signMessageWithEncryptedKey } = api; /** * Test Commands: @@ -34,6 +32,8 @@ export const testEthereumSignMessageWrappedKey = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -56,7 +56,7 @@ export const testEthereumSignMessageWrappedKey = async ( const signature = await signMessageWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', messageToSign: unsignedStringMessage, litNodeClient: devEnv.litNodeClient, }); @@ -74,7 +74,7 @@ export const testEthereumSignMessageWrappedKey = async ( const signatureBinary = await signMessageWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', messageToSign: unsignedBinaryMessage, litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testEthereumSignTransactionWrappedKey.ts b/local-tests/tests/testEthereumSignTransactionWrappedKey.ts index bb4395243c..01f045d676 100644 --- a/local-tests/tests/testEthereumSignTransactionWrappedKey.ts +++ b/local-tests/tests/testEthereumSignTransactionWrappedKey.ts @@ -1,13 +1,12 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signTransactionWithEncryptedKey, - EthereumLitTransaction, -} from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +import type { EthereumLitTransaction } from '@lit-protocol/wrapped-keys'; + +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: @@ -35,6 +34,8 @@ export const testEthereumSignTransactionWrappedKey = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -67,7 +68,7 @@ export const testEthereumSignTransactionWrappedKey = async ( const signedTx = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', unsignedTransaction, broadcast: false, litNodeClient: devEnv.litNodeClient, diff --git a/local-tests/tests/testExportWrappedKey.ts b/local-tests/tests/testExportWrappedKey.ts index 4413bc9ba8..660b721d60 100644 --- a/local-tests/tests/testExportWrappedKey.ts +++ b/local-tests/tests/testExportWrappedKey.ts @@ -1,9 +1,10 @@ import { log } from '@lit-protocol/misc'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { exportPrivateKey, importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; +const { exportPrivateKey, importPrivateKey } = api; /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testExportWrappedKey @@ -28,6 +29,8 @@ export const testExportWrappedKey = async (devEnv: TinnyEnvironment) => { pkpSessionSigs: pkpSessionSigsImport, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -46,7 +49,7 @@ export const testExportWrappedKey = async (devEnv: TinnyEnvironment) => { console.log(pkpSessionSigsExport); - const decryptedPrivateKey = await exportPrivateKey({ + const { decryptedPrivateKey } = await exportPrivateKey({ pkpSessionSigs: pkpSessionSigsExport, litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testFailCustomGenerateKeyWithBothIpfsAndCode.ts b/local-tests/tests/testFailCustomGenerateKeyWithBothIpfsAndCode.ts deleted file mode 100644 index 5098278c89..0000000000 --- a/local-tests/tests/testFailCustomGenerateKeyWithBothIpfsAndCode.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { log } from '@lit-protocol/misc'; -import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { customGeneratePrivateKey } from '@lit-protocol/wrapped-keys'; -import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { LIT_ACTION_CID_REPOSITORY } from 'packages/wrapped-keys/src/lib/constants'; - -const CUSTOM_LIT_ACTION_CODE = ` -(async () => { - const LIT_PREFIX = 'lit_'; - - 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, - }); - } - ); - - Lit.Actions.setResponse({ - response: resp, - }); -})(); -`; - -/** - * Test Commands: - * ✅ NETWORK=cayenne yarn test:local --filter=testFailCustomGenerateKeyWithBothIpfsAndCode - * ✅ NETWORK=manzano yarn test:local --filter=testFailCustomGenerateKeyWithBothIpfsAndCode - * ✅ NETWORK=localchain yarn test:local --filter=testFailCustomGenerateKeyWithBothIpfsAndCode - */ -export const testFailCustomGenerateKeyWithBothIpfsAndCode = async ( - devEnv: TinnyEnvironment -) => { - const alice = await devEnv.createRandomPerson(); - - const alicePkpSessionSigs = await getPkpSessionSigs( - devEnv, - alice, - null, - new Date(Date.now() + 1000 * 60 * 10).toISOString() - ); // 10 mins expiry - - try { - await customGeneratePrivateKey({ - pkpSessionSigs: alicePkpSessionSigs, - litActionIpfsCid: - LIT_ACTION_CID_REPOSITORY.generateEncryptedSolanaPrivateKey, - litActionCode: CUSTOM_LIT_ACTION_CODE, - litNodeClient: devEnv.litNodeClient, - }); - } catch (e: any) { - console.log('❌ THIS IS EXPECTED: ', e); - - if ( - e.message === "Can't provide both the litActionIpfsCid or litActionCode" - ) { - console.log( - '✅ testFailImportWrappedKeysWithSamePrivateKey is expected to have an error' - ); - } else { - throw e; - } - } - - log('✅ testFailCustomGenerateKeyWithBothIpfsAndCode'); -}; diff --git a/local-tests/tests/testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds.ts b/local-tests/tests/testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds.ts index 1ce50f1d5e..d83dcf710e 100644 --- a/local-tests/tests/testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds.ts +++ b/local-tests/tests/testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds.ts @@ -1,14 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signTransactionWithEncryptedKey, - EthereumLitTransaction, -} from '@lit-protocol/wrapped-keys'; +import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds @@ -34,6 +30,8 @@ export const testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds = pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -67,7 +65,7 @@ export const testFailEthereumBroadcastTransactionWrappedKeysInsufficientFunds = try { const _res = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', unsignedTransaction, broadcast: true, litNodeClient: devEnv.litNodeClient, diff --git a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts index 2800723fe8..1d23602c9f 100644 --- a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts +++ b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyInvalidDecryption.ts @@ -5,10 +5,8 @@ import { EthereumLitTransaction } 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_ACTION_CID_REPOSITORY, - LIT_PREFIX, -} from 'packages/wrapped-keys/src/lib/constants'; +import { LIT_PREFIX } from 'packages/wrapped-keys/src/lib/constants'; +import { LIT_ACTION_CID_REPOSITORY } from '../../packages/wrapped-keys/src/lib/lit-actions-client/constants'; /** * Test Commands: @@ -21,11 +19,11 @@ export const testFailEthereumSignTransactionWrappedKeyInvalidDecryption = const alice = await devEnv.createRandomPerson(); const privateKey = ethers.Wallet.createRandom().privateKey; const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; - const decryptionAccessControlConditions = + const decryptionAccessControlCondition = getPkpAccessControlCondition(alicePkpAddress); const { ciphertext, dataToEncryptHash } = await encryptString( { - accessControlConditions: decryptionAccessControlConditions, + accessControlConditions: [decryptionAccessControlCondition], dataToEncrypt: LIT_PREFIX + privateKey, }, devEnv.litNodeClient @@ -55,13 +53,12 @@ export const testFailEthereumSignTransactionWrappedKeyInvalidDecryption = try { const _res = await devEnv.litNodeClient.executeJs({ sessionSigs: pkpSessionSigsSigning, - ipfsId: - LIT_ACTION_CID_REPOSITORY.signTransactionWithEthereumEncryptedKey, + ipfsId: LIT_ACTION_CID_REPOSITORY.signTransaction.evm, jsParams: { ciphertext, dataToEncryptHash, unsignedTransaction, - accessControlConditions: decryptionAccessControlConditions, + accessControlConditions: [decryptionAccessControlCondition], }, }); } catch (e: any) { diff --git a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts index 78f4658519..2bc235417e 100644 --- a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts +++ b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithInvalidParam.ts @@ -1,14 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signTransactionWithEncryptedKey, - EthereumLitTransaction, -} from '@lit-protocol/wrapped-keys'; +import { api, EthereumLitTransaction } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailEthereumSignTransactionWrappedKeyWithInvalidParam @@ -35,6 +31,8 @@ export const testFailEthereumSignTransactionWrappedKeyWithInvalidParam = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -66,7 +64,7 @@ export const testFailEthereumSignTransactionWrappedKeyWithInvalidParam = async ( try { const _res = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, + network: 'evm', unsignedTransaction, broadcast: false, litNodeClient: devEnv.litNodeClient, diff --git a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts index 1b8788a972..4bf1f54c1d 100644 --- a/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts +++ b/local-tests/tests/testFailEthereumSignTransactionWrappedKeyWithMissingParam.ts @@ -1,14 +1,10 @@ import { log } from '@lit-protocol/misc'; import { ethers } from 'ethers'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signTransactionWithEncryptedKey, - SolanaLitTransaction, -} from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailEthereumSignTransactionWrappedKeyWithMissingParam @@ -35,6 +31,8 @@ export const testFailEthereumSignTransactionWrappedKeyWithMissingParam = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -53,17 +51,15 @@ export const testFailEthereumSignTransactionWrappedKeyWithMissingParam = async ( console.log(pkpSessionSigsSigning); - // Using SolanaLitTransaction to mimic a missing field (chainId) param as Typescript will complain about missing chainId - const unsignedTransaction: SolanaLitTransaction = { - chain: 'chronicleTestnet', - serializedTransaction: 'random-value', - }; - try { const _res = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_EVM, - unsignedTransaction, + network: 'evm', + unsignedTransaction: { + chain: 'chronicleTestnet', + // @ts-expect-error This test is intentionally using the type incorrectly. + serializedTransaction: 'random-value', + }, broadcast: false, litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testFailImportWrappedKeysWithEoaSessionSig.ts b/local-tests/tests/testFailImportWrappedKeysWithEoaSessionSig.ts index 5667d336c4..c0328d5b95 100644 --- a/local-tests/tests/testFailImportWrappedKeysWithEoaSessionSig.ts +++ b/local-tests/tests/testFailImportWrappedKeysWithEoaSessionSig.ts @@ -1,8 +1,10 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getEoaSessionSigs } from 'local-tests/setup/session-sigs/get-eoa-session-sigs'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; +const { importPrivateKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailImportWrappedKeysWithEoaSessionSig @@ -25,12 +27,14 @@ export const testFailImportWrappedKeysWithEoaSessionSig = async ( pkpSessionSigs: eoaSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); } catch (e: any) { console.log('❌ THIS IS EXPECTED: ', e); console.log(e.message); - if (e.message === 'SessionSig is not from a PKP') { + if (e.message.includes('SessionSig is not from a PKP')) { console.log( '✅ testFailImportWrappedKeysWithEoaSessionSig is expected to have an error' ); diff --git a/local-tests/tests/testFailImportWrappedKeysWithExpiredSessionSig.ts b/local-tests/tests/testFailImportWrappedKeysWithExpiredSessionSig.ts index 3f4e015932..2d95ba7deb 100644 --- a/local-tests/tests/testFailImportWrappedKeysWithExpiredSessionSig.ts +++ b/local-tests/tests/testFailImportWrappedKeysWithExpiredSessionSig.ts @@ -1,8 +1,10 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; import { SessionSigsMap } from '@lit-protocol/types'; +const { importPrivateKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailImportWrappedKeysWithExpiredSessionSig @@ -46,6 +48,8 @@ export const testFailImportWrappedKeysWithExpiredSessionSig = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); console.log(res); } catch (e: any) { diff --git a/local-tests/tests/testFailImportWrappedKeysWithInvalidSessionSig.ts b/local-tests/tests/testFailImportWrappedKeysWithInvalidSessionSig.ts index 1d17e0c5d6..05eba31796 100644 --- a/local-tests/tests/testFailImportWrappedKeysWithInvalidSessionSig.ts +++ b/local-tests/tests/testFailImportWrappedKeysWithInvalidSessionSig.ts @@ -1,9 +1,11 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; import { AuthSig, SessionSigsMap } from '@lit-protocol/types'; +const { importPrivateKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailImportWrappedKeysWithInvalidSessionSig @@ -26,6 +28,8 @@ export const testFailImportWrappedKeysWithInvalidSessionSig = async ( pkpSessionSigs: tamperPkpSessionSigs(pkpSessionSigs), privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); } catch (e: any) { console.log('❌ THIS IS EXPECTED: ', e); diff --git a/local-tests/tests/testFailImportWrappedKeysWithMaxExpirySessionSig.ts b/local-tests/tests/testFailImportWrappedKeysWithMaxExpirySessionSig.ts index a000c9f94c..08d5ddc4a9 100644 --- a/local-tests/tests/testFailImportWrappedKeysWithMaxExpirySessionSig.ts +++ b/local-tests/tests/testFailImportWrappedKeysWithMaxExpirySessionSig.ts @@ -1,8 +1,10 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; +const { importPrivateKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailImportWrappedKeysWithMaxExpirySessionSig @@ -25,6 +27,8 @@ export const testFailImportWrappedKeysWithMaxExpirySessionSig = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); } catch (e: any) { console.log('❌ THIS IS EXPECTED: ', e); diff --git a/local-tests/tests/testFailImportWrappedKeysWithSamePkp.ts b/local-tests/tests/testFailImportWrappedKeysWithSamePkp.ts index 170e82adad..8a13987b6b 100644 --- a/local-tests/tests/testFailImportWrappedKeysWithSamePkp.ts +++ b/local-tests/tests/testFailImportWrappedKeysWithSamePkp.ts @@ -1,8 +1,10 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; +const { importPrivateKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailImportWrappedKeysWithSamePkp @@ -29,6 +31,8 @@ export const testFailImportWrappedKeysWithSamePkp = async ( pkpSessionSigs, privateKey: privateKey1, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -47,6 +51,8 @@ export const testFailImportWrappedKeysWithSamePkp = async ( pkpSessionSigs, privateKey: privateKey2, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); } catch (e: any) { console.log('❌ THIS IS EXPECTED: ', e); diff --git a/local-tests/tests/testFailImportWrappedKeysWithSamePrivateKey.ts b/local-tests/tests/testFailImportWrappedKeysWithSamePrivateKey.ts index 56caa62090..868beceea4 100644 --- a/local-tests/tests/testFailImportWrappedKeysWithSamePrivateKey.ts +++ b/local-tests/tests/testFailImportWrappedKeysWithSamePrivateKey.ts @@ -1,7 +1,8 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; +const { importPrivateKey } = api; /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testFailImportWrappedKeysWithSamePrivateKey @@ -30,6 +31,8 @@ export const testFailImportWrappedKeysWithSamePrivateKey = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); } catch (e: any) { console.log('❌ THIS IS EXPECTED: ', e); diff --git a/local-tests/tests/testGenerateEthereumWrappedKey.ts b/local-tests/tests/testGenerateEthereumWrappedKey.ts index fed30a0879..379ede42bd 100644 --- a/local-tests/tests/testGenerateEthereumWrappedKey.ts +++ b/local-tests/tests/testGenerateEthereumWrappedKey.ts @@ -1,8 +1,9 @@ import { log } from '@lit-protocol/misc'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { generatePrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_EVM } from 'packages/wrapped-keys/src/lib/constants'; + +const { generatePrivateKey } = api; /** * Test Commands: @@ -26,7 +27,7 @@ export const testGenerateEthereumWrappedKey = async ( const { pkpAddress, generatedPublicKey } = await generatePrivateKey({ pkpSessionSigs, - network: NETWORK_EVM, + network: 'evm', litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testGenerateSolanaWrappedKey.ts b/local-tests/tests/testGenerateSolanaWrappedKey.ts index 253747edba..ff5217c4f0 100644 --- a/local-tests/tests/testGenerateSolanaWrappedKey.ts +++ b/local-tests/tests/testGenerateSolanaWrappedKey.ts @@ -1,14 +1,12 @@ import { log } from '@lit-protocol/misc'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - generatePrivateKey, - signMessageWithEncryptedKey, -} from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_SOLANA } from 'packages/wrapped-keys/src/lib/constants'; import nacl from 'tweetnacl'; import bs58 from 'bs58'; +const { generatePrivateKey, signMessageWithEncryptedKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testGenerateSolanaWrappedKey @@ -31,7 +29,7 @@ export const testGenerateSolanaWrappedKey = async ( const { pkpAddress, generatedPublicKey } = await generatePrivateKey({ pkpSessionSigs, - network: NETWORK_SOLANA, + network: 'solana', litNodeClient: devEnv.litNodeClient, }); @@ -57,7 +55,7 @@ export const testGenerateSolanaWrappedKey = async ( const signature = await signMessageWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_SOLANA, + network: 'solana', messageToSign, litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testImportWrappedKey.ts b/local-tests/tests/testImportWrappedKey.ts index a1025e3d75..3c168ecf7b 100644 --- a/local-tests/tests/testImportWrappedKey.ts +++ b/local-tests/tests/testImportWrappedKey.ts @@ -1,9 +1,11 @@ import { log } from '@lit-protocol/misc'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { importPrivateKey } from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; import { randomSolanaPrivateKey } from 'local-tests/setup/tinny-utils'; +const { importPrivateKey } = api; + /** * Test Commands: * ✅ NETWORK=cayenne yarn test:local --filter=testImportWrappedKey @@ -29,6 +31,8 @@ export const testImportWrappedKey = async (devEnv: TinnyEnvironment) => { pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; diff --git a/local-tests/tests/testSignMessageWithSolanaEncryptedKey.ts b/local-tests/tests/testSignMessageWithSolanaEncryptedKey.ts index 12b64b7c49..e6e68d8a77 100644 --- a/local-tests/tests/testSignMessageWithSolanaEncryptedKey.ts +++ b/local-tests/tests/testSignMessageWithSolanaEncryptedKey.ts @@ -1,14 +1,12 @@ import { log } from '@lit-protocol/misc'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - importPrivateKey, - signMessageWithEncryptedKey, -} from '@lit-protocol/wrapped-keys'; +import { api } from '@lit-protocol/wrapped-keys'; import { Keypair } from '@solana/web3.js'; import bs58 from 'bs58'; import nacl from 'tweetnacl'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_SOLANA } from 'packages/wrapped-keys/src/lib/constants'; + +const { importPrivateKey, signMessageWithEncryptedKey } = api; /** * Test Commands: @@ -37,6 +35,8 @@ export const testSignMessageWithSolanaEncryptedKey = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -59,7 +59,7 @@ export const testSignMessageWithSolanaEncryptedKey = async ( const signature = await signMessageWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_SOLANA, + network: 'solana', messageToSign, litNodeClient: devEnv.litNodeClient, }); diff --git a/local-tests/tests/testSignTransactionWithSolanaEncryptedKey.ts b/local-tests/tests/testSignTransactionWithSolanaEncryptedKey.ts index 0948a77bf9..ba0b701e93 100644 --- a/local-tests/tests/testSignTransactionWithSolanaEncryptedKey.ts +++ b/local-tests/tests/testSignTransactionWithSolanaEncryptedKey.ts @@ -1,10 +1,6 @@ import { log } from '@lit-protocol/misc'; import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; -import { - SolanaLitTransaction, - importPrivateKey, - signTransactionWithEncryptedKey, -} from '@lit-protocol/wrapped-keys'; +import { SerializedTransaction, api } from '@lit-protocol/wrapped-keys'; import { Connection, Keypair, @@ -15,7 +11,8 @@ import { clusterApiUrl, } from '@solana/web3.js'; import { getPkpSessionSigs } from 'local-tests/setup/session-sigs/get-pkp-session-sigs'; -import { NETWORK_SOLANA } from 'packages/wrapped-keys/src/lib/constants'; + +const { importPrivateKey, signTransactionWithEncryptedKey } = api; /** * Test Commands: @@ -44,6 +41,8 @@ export const testSignTransactionWithSolanaEncryptedKey = async ( pkpSessionSigs, privateKey, litNodeClient: devEnv.litNodeClient, + publicKey: '0xdeadbeef', + keyType: 'K256', }); const alicePkpAddress = alice.authMethodOwnedPkp.ethAddress; @@ -81,14 +80,14 @@ export const testSignTransactionWithSolanaEncryptedKey = async ( }) .toString('base64'); - const unsignedTransaction: SolanaLitTransaction = { + const unsignedTransaction: SerializedTransaction = { serializedTransaction, chain: 'devnet', }; const signedTx = await signTransactionWithEncryptedKey({ pkpSessionSigs: pkpSessionSigsSigning, - network: NETWORK_SOLANA, + network: 'solana', unsignedTransaction, broadcast: false, litNodeClient: devEnv.litNodeClient, diff --git a/packages/access-control-conditions/package.json b/packages/access-control-conditions/package.json index c20b3a0c5d..980b531c36 100644 --- a/packages/access-control-conditions/package.json +++ b/packages/access-control-conditions/package.json @@ -21,7 +21,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/auth-browser/package.json b/packages/auth-browser/package.json index 082106509f..877736bad0 100644 --- a/packages/auth-browser/package.json +++ b/packages/auth-browser/package.json @@ -30,7 +30,7 @@ "tags": [ "browser" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/auth-helpers/package.json b/packages/auth-helpers/package.json index 39fec04705..cbed31c757 100644 --- a/packages/auth-helpers/package.json +++ b/packages/auth-helpers/package.json @@ -28,7 +28,7 @@ "crypto": false, "stream": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/bls-sdk/package.json b/packages/bls-sdk/package.json index 5f6068541a..2cda12b09b 100644 --- a/packages/bls-sdk/package.json +++ b/packages/bls-sdk/package.json @@ -27,7 +27,7 @@ "buildOptions": { "genReact": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/constants/package.json b/packages/constants/package.json index 7bea4451af..39bdf4feb0 100644 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -20,7 +20,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/constants/src/lib/constants/autogen_internal.ts b/packages/constants/src/lib/constants/autogen_internal.ts index 3467eed024..ab0359d069 100644 --- a/packages/constants/src/lib/constants/autogen_internal.ts +++ b/packages/constants/src/lib/constants/autogen_internal.ts @@ -1,13 +1,9 @@ // This file is auto-generated by tools/scripts/gen-internal-dev.mjs export const INTERNAL_DEV = [ - 'https://167.114.17.201:443', - 'https://158.69.34.226:443', - 'https://51.195.27.82:443', - 'https://167.114.17.203:443', - 'https://167.114.17.204:443', 'https://51.38.90.145:443', 'https://167.114.17.205:443', - 'https://167.114.17.202:443', + 'https://167.114.17.204:443', + 'https://167.114.17.203:443', ]; export const INTERNAL_MIN_NODE_COUNT = 3; @@ -17,14 +13,10 @@ export const INTERNAL_DEFAULT_CONFIG = { minNodeCount: 3, debug: true, bootstrapUrls: [ - 'https://167.114.17.201:443', - 'https://158.69.34.226:443', - 'https://51.195.27.82:443', - 'https://167.114.17.203:443', - 'https://167.114.17.204:443', 'https://51.38.90.145:443', 'https://167.114.17.205:443', - 'https://167.114.17.202:443', + 'https://167.114.17.204:443', + 'https://167.114.17.203:443', ], litNetwork: 'internalDev', connectTimeout: 20000, diff --git a/packages/constants/src/lib/version.ts b/packages/constants/src/lib/version.ts index 4035e5fa36..2ef1c96f29 100644 --- a/packages/constants/src/lib/version.ts +++ b/packages/constants/src/lib/version.ts @@ -1 +1 @@ -export const version = '6.0.3-wrapped-keys.beta.3'; +export const version = '6.0.3-wrapped-keys.beta.4'; diff --git a/packages/contracts-sdk/package.json b/packages/contracts-sdk/package.json index ce819f4c96..ee706bbf4f 100644 --- a/packages/contracts-sdk/package.json +++ b/packages/contracts-sdk/package.json @@ -32,7 +32,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/core/package.json b/packages/core/package.json index eba6ea0171..0019297540 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/core", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -27,4 +27,4 @@ ], "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 822e91de15..38b99fec03 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -21,7 +21,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/ecdsa-sdk/package.json b/packages/ecdsa-sdk/package.json index 678106e818..48d6e0dc47 100644 --- a/packages/ecdsa-sdk/package.json +++ b/packages/ecdsa-sdk/package.json @@ -24,7 +24,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 55caa8b978..7be92762db 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -25,7 +25,7 @@ "crypto": false, "stream": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/lit-auth-client/package.json b/packages/lit-auth-client/package.json index ad5c39414c..c24f875b74 100644 --- a/packages/lit-auth-client/package.json +++ b/packages/lit-auth-client/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/lit-auth-client", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -31,4 +31,4 @@ }, "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/lit-node-client-nodejs/package.json b/packages/lit-node-client-nodejs/package.json index 594a675835..33bd69f527 100644 --- a/packages/lit-node-client-nodejs/package.json +++ b/packages/lit-node-client-nodejs/package.json @@ -24,7 +24,7 @@ "tags": [ "nodejs" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/lit-node-client/package.json b/packages/lit-node-client/package.json index 9777625828..8a5fd82d5d 100644 --- a/packages/lit-node-client/package.json +++ b/packages/lit-node-client/package.json @@ -28,7 +28,7 @@ "crypto": false, "stream": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/logger/package.json b/packages/logger/package.json index 0b8d92ade9..dc76a839f4 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/logger", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "tags": [ "universal" @@ -11,4 +11,4 @@ }, "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/misc-browser/package.json b/packages/misc-browser/package.json index fc0a7941aa..6e9e1961ae 100644 --- a/packages/misc-browser/package.json +++ b/packages/misc-browser/package.json @@ -21,7 +21,7 @@ "tags": [ "browser" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/misc/package.json b/packages/misc/package.json index 66eafe1e04..7900a5403e 100644 --- a/packages/misc/package.json +++ b/packages/misc/package.json @@ -24,7 +24,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/nacl/package.json b/packages/nacl/package.json index 5fd6d520f3..ac9fbe6829 100644 --- a/packages/nacl/package.json +++ b/packages/nacl/package.json @@ -21,7 +21,7 @@ "access": "public", "directory": "../../dist/packages/nacl" }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/pkp-base/package.json b/packages/pkp-base/package.json index 9127dabb92..c771b780e9 100644 --- a/packages/pkp-base/package.json +++ b/packages/pkp-base/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/pkp-base", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -27,4 +27,4 @@ ], "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/pkp-client/package.json b/packages/pkp-client/package.json index e650d84ef8..64afcf556f 100644 --- a/packages/pkp-client/package.json +++ b/packages/pkp-client/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/pkp-client", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -27,4 +27,4 @@ ], "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/pkp-cosmos/package.json b/packages/pkp-cosmos/package.json index 80569582b4..314884feff 100644 --- a/packages/pkp-cosmos/package.json +++ b/packages/pkp-cosmos/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/pkp-cosmos", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -27,4 +27,4 @@ ], "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/pkp-ethers/package.json b/packages/pkp-ethers/package.json index 50c579a225..b83aa801d3 100644 --- a/packages/pkp-ethers/package.json +++ b/packages/pkp-ethers/package.json @@ -20,7 +20,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/pkp-sui/package.json b/packages/pkp-sui/package.json index 8113276455..ac539dbff8 100644 --- a/packages/pkp-sui/package.json +++ b/packages/pkp-sui/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/pkp-sui", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -27,4 +27,4 @@ ], "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/pkp-walletconnect/package.json b/packages/pkp-walletconnect/package.json index aa29c7ef27..d7bba4ea6e 100644 --- a/packages/pkp-walletconnect/package.json +++ b/packages/pkp-walletconnect/package.json @@ -1,6 +1,6 @@ { "name": "@lit-protocol/pkp-walletconnect", - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "type": "commonjs", "license": "MIT", "homepage": "https://github.com/Lit-Protocol/js-sdk", @@ -34,4 +34,4 @@ ], "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/sev-snp-utils-sdk/package.json b/packages/sev-snp-utils-sdk/package.json index 62041dc81a..3b9b58c409 100644 --- a/packages/sev-snp-utils-sdk/package.json +++ b/packages/sev-snp-utils-sdk/package.json @@ -27,7 +27,7 @@ "buildOptions": { "genReact": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/types/package.json b/packages/types/package.json index cd671cd31f..903319a7f4 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -23,7 +23,7 @@ "buildOptions": { "genReact": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/types/src/lib/interfaces.ts b/packages/types/src/lib/interfaces.ts index e7f77aaafb..28ecbfe1d2 100644 --- a/packages/types/src/lib/interfaces.ts +++ b/packages/types/src/lib/interfaces.ts @@ -948,7 +948,7 @@ export interface DecryptZipFileWithMetadataProps extends SessionSigsOrAuthSig { export interface SessionKeySignedMessage { sessionKey: string; resources?: any[]; - capabilities: string[]; + capabilities: AuthSig[]; issuedAt: string; expiration: string; nodeAddress: string; diff --git a/packages/types/src/lib/types.ts b/packages/types/src/lib/types.ts index 2cbba01483..a75f786ba4 100644 --- a/packages/types/src/lib/types.ts +++ b/packages/types/src/lib/types.ts @@ -1,4 +1,3 @@ -import { AuthMethodType } from './enums'; import * as ethers from 'ethers'; import { @@ -7,6 +6,8 @@ import { LPACC_SOL, LPACC_EVM_BASIC, } from '@lit-protocol/accs-schemas'; + +import { AuthMethodType } from './enums'; import { AuthMethod, LitRelayConfig, @@ -14,8 +15,6 @@ import { Signature, StytchOtpProviderOptions, WebAuthnProviderOptions, -} from './interfaces'; -import { AccsOperatorParams, EthWalletProviderOptions, JsonEncryptionRetrieveRequest, @@ -78,14 +77,14 @@ export type Chain = string; * * @typedef { Object } LITChainRequiredProps */ -export type LITChainRequiredProps = { +export interface LITChainRequiredProps { name: string; symbol: string; decimals: number; - rpcUrls: Array; - blockExplorerUrls: Array; + rpcUrls: string[]; + blockExplorerUrls: string[]; vmType: string; -}; +} /** * @typedef { Object } LITEVMChain @@ -117,9 +116,7 @@ export type LITCosmosChain = LITChainRequiredProps & { * @property {string} vmType - Either EVM for an Ethereum compatible chain or SVM for a Solana compatible chain * @property {string} name - The human readable name of the chain */ -export type LITChain = { - [chainName: string]: T; -}; +export type LITChain = Record; export type LIT_NETWORKS_KEYS = | 'cayenne' @@ -199,18 +196,18 @@ export type ClaimResult = { pubkey: string; } & (T extends 'relay' ? LitRelayConfig : { signer: ethers.Signer }); -export type LitContract = { +export interface LitContract { address?: string; abi?: any; name?: string; -}; +} /** * Defines a set of contract metadata for bootstrapping * network context and interfacing with contracts on Chroncile blockchain * */ -export type LitContractContext = { +export interface LitContractContext { [index: string]: string | any; Allowlist: LitContract; @@ -224,7 +221,7 @@ export type LitContractContext = { RateLimitNFT: LitContract; Staking: LitContract; StakingBalances: LitContract; -}; +} /** * Type for a contract resolver instance which will be used @@ -232,7 +229,7 @@ export type LitContractContext = { * an instance of LitContractContext can still be provided. which will be used for abi data. * */ -export type LitContractResolverContext = { +export interface LitContractResolverContext { [index: string]: | string | LitContractContext @@ -244,6 +241,6 @@ export type LitContractResolverContext = { environment: number; contractContext?: LitContractContext; provider?: ethers.providers.JsonRpcProvider; -}; +} export type ResponseStrategy = 'leastCommon' | 'mostCommon' | 'custom'; diff --git a/packages/uint8arrays/package.json b/packages/uint8arrays/package.json index 1f97108f65..73f7b35b2b 100644 --- a/packages/uint8arrays/package.json +++ b/packages/uint8arrays/package.json @@ -21,7 +21,7 @@ "tags": [ "universal" ], - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/wrapped-keys/package.json b/packages/wrapped-keys/package.json index 027e8f5ed9..e071720405 100644 --- a/packages/wrapped-keys/package.json +++ b/packages/wrapped-keys/package.json @@ -23,10 +23,10 @@ "buildOptions": { "genReact": false }, - "version": "6.0.3-wrapped-keys.beta.3", + "version": "6.0.3-wrapped-keys.beta.4", "scripts": { "bundle": "yarn node ./esbuild.config.js" }, "main": "./dist/src/index.js", "typings": "./dist/src/index.d.ts" -} \ No newline at end of file +} diff --git a/packages/wrapped-keys/src/index.ts b/packages/wrapped-keys/src/index.ts index b3aca92af0..fe605532cb 100644 --- a/packages/wrapped-keys/src/index.ts +++ b/packages/wrapped-keys/src/index.ts @@ -1,3 +1,78 @@ -export * from './lib/wrapped-keys'; -export * from './lib/interfaces'; -export { NETWORK_EVM, NETWORK_SOLANA } from './lib/constants'; +import { + signMessageWithEncryptedKey, + getEncryptedKeyMetadata, + exportPrivateKey, + generatePrivateKey, + importPrivateKey, + signTransactionWithEncryptedKey, + storeEncryptedKeyMetadata, +} from './lib/api'; +import { + CHAIN_ETHEREUM, + LIT_PREFIX, + NETWORK_EVM, + NETWORK_SOLANA, + KEYTYPE_K256, + KEYTYPE_ED25519, +} from './lib/constants'; + +import type { SupportedNetworks } from './lib/service-client/types'; +import type { + SignMessageWithEncryptedKeyParams, + GetEncryptedKeyMetadataParams, + ExportPrivateKeyParams, + GeneratePrivateKeyParams, + ImportPrivateKeyParams, + SignTransactionWithEncryptedKeyParams, + ExportPrivateKeyResult, + GeneratePrivateKeyResult, + EthereumLitTransaction, + SerializedTransaction, + BaseApiParams, + ApiParamsSupportedNetworks, + SignTransactionParams, + SignTransactionParamsSupportedEvm, + SignTransactionParamsSupportedSolana, + StoreEncryptedKeyMetadataParams, + StoredKeyMetadata, +} from './lib/types'; + +export const constants = { + CHAIN_ETHEREUM, + LIT_PREFIX, + NETWORK_EVM, + NETWORK_SOLANA, + KEYTYPE_K256, + KEYTYPE_ED25519, +}; + +export const api = { + exportPrivateKey, + generatePrivateKey, + getEncryptedKeyMetadata, + importPrivateKey, + signMessageWithEncryptedKey, + signTransactionWithEncryptedKey, + storeEncryptedKeyMetadata, +}; + +export { + ApiParamsSupportedNetworks, + BaseApiParams, + EthereumLitTransaction, + ExportPrivateKeyParams, + ExportPrivateKeyResult, + GetEncryptedKeyMetadataParams, + GeneratePrivateKeyParams, + GeneratePrivateKeyResult, + ImportPrivateKeyParams, + SerializedTransaction, + SignTransactionParams, + SignTransactionParamsSupportedEvm, + SignTransactionParamsSupportedSolana, + SignMessageWithEncryptedKeyParams, + SignTransactionWithEncryptedKeyParams, + StoreEncryptedKeyMetadataParams, + StoredKeyMetadata, + SupportedNetworks, +}; diff --git a/packages/wrapped-keys/src/lib/api/export-private-key.ts b/packages/wrapped-keys/src/lib/api/export-private-key.ts new file mode 100644 index 0000000000..d672058a02 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/export-private-key.ts @@ -0,0 +1,55 @@ +import { decryptToString } from '@lit-protocol/encryption'; + +import { CHAIN_ETHEREUM, LIT_PREFIX } from '../constants'; +import { fetchPrivateKeyMetadata } from '../service-client'; +import { ExportPrivateKeyParams, ExportPrivateKeyResult } from '../types'; +import { + getFirstSessionSig, + getPkpAccessControlCondition, + getPkpAddressFromSessionSig, +} from '../utils'; + +/** Exports a previously persisted private key from the wrapped keys service for direct use by the caller, along with the keys metadata + * + * @param { ExportPrivateKeyParams } params Parameters required to export the private key + */ +export async function exportPrivateKey( + params: ExportPrivateKeyParams +): Promise { + const { pkpSessionSigs, litNodeClient } = params; + + const sessionSig = getFirstSessionSig(pkpSessionSigs); + const pkpAddress = getPkpAddressFromSessionSig(sessionSig); + const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); + + const privateKeyMetadata = await fetchPrivateKeyMetadata({ + sessionSig, + litNetwork: litNodeClient.config.litNetwork, + }); + + const { ciphertext, dataToEncryptHash, ...privateKeyMetadataMinusEncrypted } = + privateKeyMetadata; + + const decryptedPrivateKey = await decryptToString( + { + accessControlConditions: [allowPkpAddressToDecrypt], + chain: CHAIN_ETHEREUM, + ciphertext, + dataToEncryptHash, + sessionSigs: pkpSessionSigs, + }, + litNodeClient + ); + + // It will be of the form lit_ + if (!decryptedPrivateKey.startsWith(LIT_PREFIX)) { + throw new Error( + `PKey was not encrypted with salt; all wrapped keys must be prefixed with '${LIT_PREFIX}'` + ); + } + + return { + decryptedPrivateKey: decryptedPrivateKey.slice(LIT_PREFIX.length), + ...privateKeyMetadataMinusEncrypted, + }; +} diff --git a/packages/wrapped-keys/src/lib/api/generate-private-key.ts b/packages/wrapped-keys/src/lib/api/generate-private-key.ts new file mode 100644 index 0000000000..501840ebd7 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/generate-private-key.ts @@ -0,0 +1,70 @@ +import { NETWORK_EVM, NETWORK_SOLANA } from '../constants'; +import { generateKeyWithLitAction } from '../lit-actions-client'; +import { getLitActionCid } from '../lit-actions-client/utils'; +import { storePrivateKeyMetadata } from '../service-client'; +import { + GeneratePrivateKeyParams, + GeneratePrivateKeyResult, + KeyType, + Network, +} from '../types'; +import { + getFirstSessionSig, + getPkpAccessControlCondition, + getPkpAddressFromSessionSig, +} from '../utils'; + +function getKeyTypeFromNetwork(network: Network): KeyType { + if (network === NETWORK_EVM) { + return 'K256'; + } else if (network === NETWORK_SOLANA) { + return 'ed25519'; + } else { + throw new Error('Network not implemented in generate-private-key'); + } +} +/** + * Generates a random private key inside a Lit Action, and persists the key and its metadata to the wrapped keys service. + * Returns the public key of the random private key, and the PKP address that it was associated with. + * We don't return the generated wallet address since it can be derived from the publicKey + * + * The key will be associated with the PKP address embedded in the `pkpSessionSigs` you provide. One and only one wrapped key can be associated with a given LIT PKP. + * + * @param { GeneratePrivateKeyParams } params - Required parameters to generate the private key + * + * @returns { Promise } - The publicKey of the generated random private key and the LIT PKP Address associated with the Wrapped Key + */ +export async function generatePrivateKey( + params: GeneratePrivateKeyParams +): Promise { + const { pkpSessionSigs, network, litNodeClient } = params; + + const firstSessionSig = getFirstSessionSig(pkpSessionSigs); + const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); + const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); + + const { ciphertext, dataToEncryptHash, publicKey } = + await generateKeyWithLitAction({ + ...params, + pkpAddress, + litActionIpfsCid: getLitActionCid(network, 'generateEncryptedKey'), + accessControlConditions: [allowPkpAddressToDecrypt], + }); + + await storePrivateKeyMetadata({ + sessionSig: firstSessionSig, + storedKeyMetadata: { + ciphertext, + publicKey, + keyType: getKeyTypeFromNetwork(network), + dataToEncryptHash, + pkpAddress, + }, + litNetwork: litNodeClient.config.litNetwork, + }); + + return { + pkpAddress, + generatedPublicKey: publicKey, + }; +} diff --git a/packages/wrapped-keys/src/lib/api/get-encrypted-key-metadata.ts b/packages/wrapped-keys/src/lib/api/get-encrypted-key-metadata.ts new file mode 100644 index 0000000000..3b82540a93 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/get-encrypted-key-metadata.ts @@ -0,0 +1,19 @@ +import { fetchPrivateKeyMetadata } from '../service-client'; +import { GetEncryptedKeyMetadataParams, StoredKeyMetadata } from '../types'; +import { getFirstSessionSig } from '../utils'; + +/** Get a previously encrypted and persisted private key and its metadata. + * Note that this method does _not_ decrypt the private key; only the _encrypted_ key and its metadata will be returned to the caller. + * + * @param { GetEncryptedKeyMetadataParams } params Parameters required to fetch the encrypted private key metadata + * @returns { Promise } The encrypted private key and its associated metadata + */ +export async function getEncryptedKeyMetadata( + params: GetEncryptedKeyMetadataParams +): Promise { + const { pkpSessionSigs, litNodeClient } = params; + return fetchPrivateKeyMetadata({ + sessionSig: getFirstSessionSig(pkpSessionSigs), + litNetwork: litNodeClient.config.litNetwork, + }); +} diff --git a/packages/wrapped-keys/src/lib/api/import-private-key.ts b/packages/wrapped-keys/src/lib/api/import-private-key.ts new file mode 100644 index 0000000000..8fbf5ca824 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/import-private-key.ts @@ -0,0 +1,54 @@ +import { encryptString } from '@lit-protocol/encryption'; + +import { LIT_PREFIX } from '../constants'; +import { storePrivateKeyMetadata } from '../service-client'; +import { ImportPrivateKeyParams } from '../types'; +import { + getFirstSessionSig, + getPkpAccessControlCondition, + getPkpAddressFromSessionSig, +} from '../utils'; + +/** + * Import a provided private key into the wrapped keys service backend. + * First, the key is pre-pended with `LIT_PREFIX` for security reasons, then the salted key is encrypted and stored in the backend service. + * The key will be associated with the PKP address embedded in the `pkpSessionSigs` you provide. One and only one wrapped key can be associated with a given LIT PKP. + * + * @param { ImportPrivateKeyParams } params The parameters required to import the private key into the wrapped keys backend service + * + * @returns { Promise } - The LIT PKP Address associated with the Wrapped Key + */ +export async function importPrivateKey( + params: ImportPrivateKeyParams +): Promise { + const { pkpSessionSigs, privateKey, publicKey, keyType, litNodeClient } = + params; + + const firstSessionSig = getFirstSessionSig(pkpSessionSigs); + const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); + const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); + + const saltedPrivateKey = LIT_PREFIX + privateKey; + + const { ciphertext, dataToEncryptHash } = await encryptString( + { + accessControlConditions: [allowPkpAddressToDecrypt], + dataToEncrypt: saltedPrivateKey, + }, + litNodeClient + ); + + await storePrivateKeyMetadata({ + sessionSig: firstSessionSig, + litNetwork: litNodeClient.config.litNetwork, + storedKeyMetadata: { + ciphertext, + publicKey, + keyType, + dataToEncryptHash, + pkpAddress, + }, + }); + + return pkpAddress; +} diff --git a/packages/wrapped-keys/src/lib/api/index.ts b/packages/wrapped-keys/src/lib/api/index.ts new file mode 100644 index 0000000000..a20f61a866 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/index.ts @@ -0,0 +1,17 @@ +import { exportPrivateKey } from './export-private-key'; +import { generatePrivateKey } from './generate-private-key'; +import { getEncryptedKeyMetadata } from './get-encrypted-key-metadata'; +import { importPrivateKey } from './import-private-key'; +import { signMessageWithEncryptedKey } from './sign-message-with-encrypted-key'; +import { signTransactionWithEncryptedKey } from './sign-transaction-with-encrypted-key'; +import { storeEncryptedKeyMetadata } from './store-encrypted-key-metadata'; + +export { + generatePrivateKey, + importPrivateKey, + signTransactionWithEncryptedKey, + exportPrivateKey, + signMessageWithEncryptedKey, + storeEncryptedKeyMetadata, + getEncryptedKeyMetadata, +}; diff --git a/packages/wrapped-keys/src/lib/api/sign-message-with-encrypted-key.ts b/packages/wrapped-keys/src/lib/api/sign-message-with-encrypted-key.ts new file mode 100644 index 0000000000..65041197ed --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/sign-message-with-encrypted-key.ts @@ -0,0 +1,38 @@ +import { signMessageWithLitAction } from '../lit-actions-client'; +import { getLitActionCid } from '../lit-actions-client/utils'; +import { fetchPrivateKeyMetadata } from '../service-client'; +import { SignMessageWithEncryptedKeyParams } from '../types'; +import { getFirstSessionSig, getPkpAccessControlCondition } from '../utils'; + +/** + * Signs a message inside the Lit Action using the previously persisted wrapped key associated with the current LIT PK. + * This method fetches the encrypted key from the wrapped keys service, then executes a Lit Action that decrypts the key inside the LIT action and uses + * the decrypted key to sign the provided transaction + * + * @param { SignMessageWithEncryptedKeyParams } params Parameters to use for signing the message + * + * @returns { Promise } - The signed message + */ +export async function signMessageWithEncryptedKey( + params: SignMessageWithEncryptedKeyParams +): Promise { + const { litNodeClient, network, pkpSessionSigs } = params; + + const sessionSig = getFirstSessionSig(pkpSessionSigs); + const storedKeyMetadata = await fetchPrivateKeyMetadata({ + sessionSig, + litNetwork: litNodeClient.config.litNetwork, + }); + + const allowPkpAddressToDecrypt = getPkpAccessControlCondition( + storedKeyMetadata.pkpAddress + ); + + return signMessageWithLitAction({ + ...params, + litActionIpfsCid: getLitActionCid(network, 'signMessage'), + accessControlConditions: [allowPkpAddressToDecrypt], + pkpSessionSigs, + storedKeyMetadata, + }); +} diff --git a/packages/wrapped-keys/src/lib/api/sign-transaction-with-encrypted-key.ts b/packages/wrapped-keys/src/lib/api/sign-transaction-with-encrypted-key.ts new file mode 100644 index 0000000000..d3c8970ee5 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/sign-transaction-with-encrypted-key.ts @@ -0,0 +1,38 @@ +import { signTransactionWithLitAction } from '../lit-actions-client'; +import { getLitActionCid } from '../lit-actions-client/utils'; +import { fetchPrivateKeyMetadata } from '../service-client'; +import { SignTransactionWithEncryptedKeyParams } from '../types'; +import { getFirstSessionSig, getPkpAccessControlCondition } from '../utils'; + +/** + * Signs a transaction inside the Lit Action using the previously persisted wrapped key associated with the current LIT PK. + * This method fetches the encrypted key from the wrapped keys service, then executes a Lit Action that decrypts the key inside the LIT action and uses + * the decrypted key to sign the provided transaction + * Optionally, if you pass `broadcast: true`, the LIT action will also submit the signed transaction to the associated RPC endpoint on your behalf + * + * @param { SignTransactionWithEncryptedKeyParams } params Parameters required to sign the requested transaction + * + * @returns { string } The signed transaction OR its transaction hash if you set `broadcast: true` and the LIT action supports this functionality. + */ +export async function signTransactionWithEncryptedKey( + params: SignTransactionWithEncryptedKeyParams +): Promise { + const { litNodeClient, network, pkpSessionSigs } = params; + const sessionSig = getFirstSessionSig(pkpSessionSigs); + + const storedKeyMetadata = await fetchPrivateKeyMetadata({ + sessionSig, + litNetwork: litNodeClient.config.litNetwork, + }); + + const allowPkpAddressToDecrypt = getPkpAccessControlCondition( + storedKeyMetadata.pkpAddress + ); + + return signTransactionWithLitAction({ + ...params, + litActionIpfsCid: getLitActionCid(network, 'signTransaction'), + storedKeyMetadata, + accessControlConditions: [allowPkpAddressToDecrypt], + }); +} diff --git a/packages/wrapped-keys/src/lib/api/store-encrypted-key-metadata.ts b/packages/wrapped-keys/src/lib/api/store-encrypted-key-metadata.ts new file mode 100644 index 0000000000..462bd349f1 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/store-encrypted-key-metadata.ts @@ -0,0 +1,30 @@ +import { storePrivateKeyMetadata } from '../service-client'; +import { StoreEncryptedKeyMetadataParams } from '../types'; +import { getFirstSessionSig, getPkpAddressFromSessionSig } from '../utils'; + +/** Stores an encrypted private key and its metadata to the wrapped keys backend service + * + * @param { StoreEncryptedKeyMetadataParams } params Parameters required to fetch the encrypted private key metadata + * @returns { Promise } The encrypted private key and its associated metadata + */ +export async function storeEncryptedKeyMetadata( + params: StoreEncryptedKeyMetadataParams +): Promise { + const { pkpSessionSigs, litNodeClient } = params; + const sessionSig = getFirstSessionSig(pkpSessionSigs); + const pkpAddress = getPkpAddressFromSessionSig(sessionSig); + + const { publicKey, keyType, dataToEncryptHash, ciphertext } = params; + + return storePrivateKeyMetadata({ + storedKeyMetadata: { + publicKey, + keyType, + dataToEncryptHash, + ciphertext, + pkpAddress, + }, + sessionSig: getFirstSessionSig(pkpSessionSigs), + litNetwork: litNodeClient.config.litNetwork, + }); +} diff --git a/packages/wrapped-keys/src/lib/constants.ts b/packages/wrapped-keys/src/lib/constants.ts index e24bcc721e..52b737cf12 100644 --- a/packages/wrapped-keys/src/lib/constants.ts +++ b/packages/wrapped-keys/src/lib/constants.ts @@ -1,31 +1,10 @@ -const CHAIN_ETHEREUM = 'ethereum'; -const LIT_PREFIX = 'lit_'; -export const NETWORK_EVM = 'evm'; -export const NETWORK_SOLANA = 'solana'; -export type Network = typeof NETWORK_EVM | typeof NETWORK_SOLANA; +import { Network, KeyType } from './types'; -// Update the endpoint to Wrapped Key project endpoint -const ENCRYPTED_PRIVATE_KEY_ENDPOINT = - 'https://8wugrwstu1.execute-api.us-east-2.amazonaws.com/encrypted'; +export const CHAIN_ETHEREUM = 'ethereum'; +export const LIT_PREFIX = 'lit_'; -const LIT_ACTION_CID_REPOSITORY = Object.freeze({ - signTransactionWithSolanaEncryptedKey: - 'QmSi9GL2weCFEP1SMAUw5PDpZRr436Zt3tLUNrSECPA5dT', - signTransactionWithEthereumEncryptedKey: - 'QmdYUhPCCK5hpDWMK1NiDLNLG6RZQy61QE4J7dBm1Y2nbA', - signMessageWithSolanaEncryptedKey: - 'QmYQC6cd4EMvyB4XPkfEEAwNXJupRZWU5JsTCUrjey4ovp', - signMessageWithEthereumEncryptedKey: - 'QmTMGcyp77NeppGaqF2DmE1F8GXTSxQYzXCrbE7hNudUWx', - generateEncryptedSolanaPrivateKey: - 'QmdRBXYLYvcNHrChmsZ2jFDY8dA99CcSdqHo3p1ES3UThL', - generateEncryptedEthereumPrivateKey: - 'QmaoPMSqcze3NW3KSA75ecWSkcmWT1J7kVr8LyJPCKRvHd', -}); +export const NETWORK_EVM: Network = 'evm'; +export const NETWORK_SOLANA: Network = 'solana'; -export { - CHAIN_ETHEREUM, - ENCRYPTED_PRIVATE_KEY_ENDPOINT, - LIT_ACTION_CID_REPOSITORY, - LIT_PREFIX, -}; +export const KEYTYPE_K256: KeyType = 'K256'; +export const KEYTYPE_ED25519: KeyType = 'ed25519'; diff --git a/packages/wrapped-keys/src/lib/interfaces.ts b/packages/wrapped-keys/src/lib/interfaces.ts deleted file mode 100644 index df2813bac0..0000000000 --- a/packages/wrapped-keys/src/lib/interfaces.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ILitNodeClient, SessionSigsMap } from '@lit-protocol/types'; -import { Network } from './constants'; - -export interface StoreToDatabaseParams { - ciphertext: string; - dataToEncryptHash: string; -} - -export interface CustomGeneratePrivateKeyParams { - pkpSessionSigs: SessionSigsMap; - litActionIpfsCid?: string; - litActionCode?: string; - litNodeClient: ILitNodeClient; -} - -export interface GeneratePrivateKeyParams { - pkpSessionSigs: SessionSigsMap; - network: Network; - litNodeClient: ILitNodeClient; -} - -export interface GeneratePrivateKeyResponse { - pkpAddress: string; - generatedPublicKey: string; -} - -export interface ImportPrivateKeyParams { - pkpSessionSigs: SessionSigsMap; - privateKey: string; - litNodeClient: ILitNodeClient; -} - -export interface ImportPrivateKeyResponse { - pkpAddress: string; -} - -export interface ExportPrivateKeyParams { - pkpSessionSigs: SessionSigsMap; - litNodeClient: ILitNodeClient; -} - -export interface ExportPrivateKeyResponse { - pkpAddress: string; - ciphertext: string; - dataToEncryptHash: string; -} - -export interface CustomSignMessageWithEncryptedKeyParams { - pkpSessionSigs: SessionSigsMap; - litActionIpfsCid?: string; - litActionCode?: string; - messageToSign: string | Uint8Array; - params?: Record; - litNodeClient: ILitNodeClient; -} - -export interface SignMessageWithEncryptedKeyParams { - pkpSessionSigs: SessionSigsMap; - network: Network; - messageToSign: string | Uint8Array; - litNodeClient: ILitNodeClient; -} - -export interface SignTransactionWithEncryptedKeyParams { - pkpSessionSigs: SessionSigsMap; - network: Network; - unsignedTransaction: T; - broadcast: boolean; - litNodeClient: ILitNodeClient; -} - -export interface CustomSignTransactionWithEncryptedKeyParams { - pkpSessionSigs: SessionSigsMap; - litActionIpfsCid?: string; - litActionCode?: string; - serializedTransaction: string; - broadcast: boolean; - params?: Record; - litNodeClient: ILitNodeClient; -} - -interface BaseLitTransaction { - chain: string; -} - -export interface EthereumLitTransaction extends BaseLitTransaction { - toAddress: string; - value: string; - chainId: number; - gasPrice?: string; - gasLimit?: number; - dataHex?: string; -} - -export interface SolanaLitTransaction extends BaseLitTransaction { - serializedTransaction: string; -} - -export type LitTransaction = EthereumLitTransaction | SolanaLitTransaction; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts b/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts new file mode 100644 index 0000000000..133257b2fe --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts @@ -0,0 +1,18 @@ +import { LitCidRepository } from './types'; + +const LIT_ACTION_CID_REPOSITORY: LitCidRepository = { + signTransaction: Object.freeze({ + evm: 'QmdYUhPCCK5hpDWMK1NiDLNLG6RZQy61QE4J7dBm1Y2nbA', + solana: 'QmSi9GL2weCFEP1SMAUw5PDpZRr436Zt3tLUNrSECPA5dT', + }), + signMessage: Object.freeze({ + evm: 'QmTMGcyp77NeppGaqF2DmE1F8GXTSxQYzXCrbE7hNudUWx', + solana: 'QmYQC6cd4EMvyB4XPkfEEAwNXJupRZWU5JsTCUrjey4ovp', + }), + generateEncryptedKey: Object.freeze({ + evm: 'QmaoPMSqcze3NW3KSA75ecWSkcmWT1J7kVr8LyJPCKRvHd', + solana: 'QmdRBXYLYvcNHrChmsZ2jFDY8dA99CcSdqHo3p1ES3UThL', + }), +}; + +export { LIT_ACTION_CID_REPOSITORY }; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/generate-key.ts b/packages/wrapped-keys/src/lib/lit-actions-client/generate-key.ts new file mode 100644 index 0000000000..097d3d3ee3 --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/generate-key.ts @@ -0,0 +1,42 @@ +import { AccessControlConditions } from '@lit-protocol/types'; + +import { postLitActionValidation } from './utils'; +import { GeneratePrivateKeyParams } from '../types'; + +interface GeneratePrivateKeyLitActionParams extends GeneratePrivateKeyParams { + pkpAddress: string; + accessControlConditions: AccessControlConditions; + litActionIpfsCid: string; +} + +interface GeneratePrivateKeyLitActionResult { + ciphertext: string; + dataToEncryptHash: string; + publicKey: string; +} + +export async function generateKeyWithLitAction({ + litNodeClient, + pkpSessionSigs, + litActionIpfsCid, + accessControlConditions, + pkpAddress, +}: GeneratePrivateKeyLitActionParams): Promise { + try { + const result = await litNodeClient.executeJs({ + sessionSigs: pkpSessionSigs, + ipfsId: litActionIpfsCid, + jsParams: { + pkpAddress, + accessControlConditions, + }, + }); + + const response = postLitActionValidation(result); + return JSON.parse(response); + } catch (err: any) { + throw new Error( + `Lit Action threw an unexpected error: ${JSON.stringify(err)}` + ); + } +} diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/index.ts b/packages/wrapped-keys/src/lib/lit-actions-client/index.ts new file mode 100644 index 0000000000..518465e5bb --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/index.ts @@ -0,0 +1,9 @@ +import { generateKeyWithLitAction } from './generate-key'; +import { signMessageWithLitAction } from './sign-message'; +import { signTransactionWithLitAction } from './sign-transaction'; + +export { + generateKeyWithLitAction, + signTransactionWithLitAction, + signMessageWithLitAction, +}; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/sign-message.ts b/packages/wrapped-keys/src/lib/lit-actions-client/sign-message.ts new file mode 100644 index 0000000000..b6fc11021b --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/sign-message.ts @@ -0,0 +1,44 @@ +import { AccessControlConditions } from '@lit-protocol/types'; + +import { postLitActionValidation } from './utils'; +import { SignMessageWithEncryptedKeyParams, StoredKeyMetadata } from '../types'; + +interface SignMessageWithLitActionParams + extends SignMessageWithEncryptedKeyParams { + accessControlConditions: AccessControlConditions; + storedKeyMetadata: StoredKeyMetadata; + litActionIpfsCid: string; +} + +export async function signMessageWithLitAction( + args: SignMessageWithLitActionParams +) { + const { + accessControlConditions, + litNodeClient, + messageToSign, + pkpSessionSigs, + litActionIpfsCid, + storedKeyMetadata, + } = args; + + try { + const { pkpAddress, ciphertext, dataToEncryptHash } = storedKeyMetadata; + const result = await litNodeClient.executeJs({ + sessionSigs: pkpSessionSigs, + ipfsId: litActionIpfsCid, + jsParams: { + pkpAddress, + ciphertext, + dataToEncryptHash, + messageToSign, + accessControlConditions, + }, + }); + return postLitActionValidation(result); + } catch (err: any) { + throw new Error( + `Lit Action threw an unexpected error: ${JSON.stringify(err)}` + ); + } +} diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/sign-transaction.ts b/packages/wrapped-keys/src/lib/lit-actions-client/sign-transaction.ts new file mode 100644 index 0000000000..63697b1601 --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/sign-transaction.ts @@ -0,0 +1,53 @@ +import { + AccessControlConditions, + ILitNodeClient, + SessionSigsMap, +} from '@lit-protocol/types'; + +import { postLitActionValidation } from './utils'; +import { + EthereumLitTransaction, + SerializedTransaction, + StoredKeyMetadata, +} from '../types'; + +interface SignTransactionWithLitActionParams { + litNodeClient: ILitNodeClient; + pkpSessionSigs: SessionSigsMap; + litActionIpfsCid: string; + unsignedTransaction: EthereumLitTransaction | SerializedTransaction; + storedKeyMetadata: StoredKeyMetadata; + accessControlConditions: AccessControlConditions; + broadcast: boolean; +} + +export async function signTransactionWithLitAction({ + accessControlConditions, + broadcast, + litActionIpfsCid, + litNodeClient, + pkpSessionSigs, + storedKeyMetadata: { ciphertext, dataToEncryptHash, pkpAddress }, + unsignedTransaction, +}: SignTransactionWithLitActionParams): Promise { + try { + const result = await litNodeClient.executeJs({ + sessionSigs: pkpSessionSigs, + ipfsId: litActionIpfsCid, + jsParams: { + pkpAddress, + ciphertext, + dataToEncryptHash, + unsignedTransaction, + broadcast, + accessControlConditions, + }, + }); + + return postLitActionValidation(result); + } catch (err: any) { + throw new Error( + `Lit Action threw an unexpected error: ${JSON.stringify(err)}` + ); + } +} diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/types.ts b/packages/wrapped-keys/src/lib/lit-actions-client/types.ts new file mode 100644 index 0000000000..3b2f653b89 --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/types.ts @@ -0,0 +1,12 @@ +import { Network } from '../types'; + +export type LitActionType = + | 'signTransaction' + | 'signMessage' + | 'generateEncryptedKey'; + +export type LitCidRepositoryEntry = Readonly>; + +export type LitCidRepository = Readonly< + Record +>; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/utils.ts b/packages/wrapped-keys/src/lib/lit-actions-client/utils.ts new file mode 100644 index 0000000000..c993199985 --- /dev/null +++ b/packages/wrapped-keys/src/lib/lit-actions-client/utils.ts @@ -0,0 +1,50 @@ +import { ExecuteJsResponse } from '@lit-protocol/types'; + +import { LIT_ACTION_CID_REPOSITORY } from './constants'; +import { LitActionType } from './types'; +import { Network } from '../types'; + +/** + * + * Post processes the Lit Action result to ensure that the result is non-empty and a valid string + * + * @param result - The Lit Action result to be processes + * + * @returns { string } - The response field in the Lit Action result object + */ +export function postLitActionValidation( + result: ExecuteJsResponse | undefined +): string { + if (!result) { + throw new Error('There was an unknown error running the Lit Action.'); + } + + const { response } = result; + if (!response) { + throw new Error( + `Expected "response" in Lit Action result: ${JSON.stringify(result)}` + ); + } + + if (typeof response !== 'string') { + // As the return value is a hex string + throw new Error( + `Lit Action should return a string response: ${JSON.stringify(result)}` + ); + } + + if (!result.success) { + throw new Error(`Expected "success" in res: ${JSON.stringify(result)}`); + } + + if (response.startsWith('Error:')) { + // Lit Action sets an error response + throw new Error(`Error executing the Signing Lit Action: ${response}`); + } + + return response; +} + +export function getLitActionCid(network: Network, actionType: LitActionType) { + return LIT_ACTION_CID_REPOSITORY[actionType][network]; +} diff --git a/packages/wrapped-keys/src/lib/litActions/solana/src/signTransactionWithSolanaEncryptedKey.js b/packages/wrapped-keys/src/lib/litActions/solana/src/signTransactionWithSolanaEncryptedKey.js index a1e8706ce7..c398eef491 100644 --- a/packages/wrapped-keys/src/lib/litActions/solana/src/signTransactionWithSolanaEncryptedKey.js +++ b/packages/wrapped-keys/src/lib/litActions/solana/src/signTransactionWithSolanaEncryptedKey.js @@ -82,7 +82,7 @@ const { clusterApiUrl(unsignedTransaction.chain), 'confirmed' ); - await solanaConnection.sendRawTransaction(transaction.serialize()); + await solanaConnection.sendRawTransaction(transaction.serialize()); // FIXME: Shouldn't this return the tx hash for consistency with the evm action? } } catch (error) { Lit.Actions.setResponse({ diff --git a/packages/wrapped-keys/src/lib/service-client/client.ts b/packages/wrapped-keys/src/lib/service-client/client.ts new file mode 100644 index 0000000000..542ed03483 --- /dev/null +++ b/packages/wrapped-keys/src/lib/service-client/client.ts @@ -0,0 +1,52 @@ +import { FetchKeyParams, StoreKeyParams } from './types'; +import { getBaseRequestParams, makeRequest } from './utils'; +import { StoredKeyMetadata } from '../types'; + +/** Fetches previously stored private key metadata from the wrapped keys service + * + * @param { FetchKeyParams } params Parameters required to fetch the private key metadata + * @returns { Promise } The private key metadata object + */ +export async function fetchPrivateKeyMetadata( + params: FetchKeyParams +): Promise { + const { litNetwork, sessionSig } = params; + + const { url, initParams } = getBaseRequestParams({ + litNetwork, + sessionSig, + method: 'GET', + }); + + return makeRequest({ + url, + init: initParams, + }); +} + +/** Stores private key metadata into the wrapped keys service backend + * + * @param { StoreKeyParams } params Parameters required to store the private key metadata + * @returns { Promise } `true` on successful write to the service. Otherwise, this method throws an error. + */ +export async function storePrivateKeyMetadata( + params: StoreKeyParams +): Promise { + const { litNetwork, sessionSig, storedKeyMetadata } = params; + + const { url, initParams } = getBaseRequestParams({ + litNetwork, + sessionSig, + method: 'POST', + }); + + await makeRequest({ + url, + init: { + ...initParams, + body: JSON.stringify(storedKeyMetadata), + }, + }); + + return true; +} diff --git a/packages/wrapped-keys/src/lib/service-client/constants.ts b/packages/wrapped-keys/src/lib/service-client/constants.ts new file mode 100644 index 0000000000..ab22a4df80 --- /dev/null +++ b/packages/wrapped-keys/src/lib/service-client/constants.ts @@ -0,0 +1,17 @@ +import { LitNetwork } from '@lit-protocol/constants'; + +import { SupportedNetworks } from './types'; + +type NETWORK_TYPES = 'TestNetworks' | 'Production'; +const SERVICE_URL_BY_NETWORKTYPE: Record = { + TestNetworks: 'https://test.wrapped.litprotocol.com/encrypted', + Production: 'https://wrapped.litprotocol.com/encrypted', +}; + +export const SERVICE_URL_BY_LIT_NETWORK: Record = { + [LitNetwork.Cayenne]: SERVICE_URL_BY_NETWORKTYPE.TestNetworks, + [LitNetwork.Manzano]: SERVICE_URL_BY_NETWORKTYPE.TestNetworks, + [LitNetwork.Habanero]: SERVICE_URL_BY_NETWORKTYPE.Production, +}; + +export const LIT_SESSIONSIG_AUTHORIZATION_SCHEMA_PREFIX = 'LitSessionSig:'; diff --git a/packages/wrapped-keys/src/lib/service-client/index.ts b/packages/wrapped-keys/src/lib/service-client/index.ts new file mode 100644 index 0000000000..a770c11569 --- /dev/null +++ b/packages/wrapped-keys/src/lib/service-client/index.ts @@ -0,0 +1,3 @@ +import { fetchPrivateKeyMetadata, storePrivateKeyMetadata } from './client'; + +export { fetchPrivateKeyMetadata, storePrivateKeyMetadata }; diff --git a/packages/wrapped-keys/src/lib/service-client/types.ts b/packages/wrapped-keys/src/lib/service-client/types.ts new file mode 100644 index 0000000000..c4cff96e20 --- /dev/null +++ b/packages/wrapped-keys/src/lib/service-client/types.ts @@ -0,0 +1,28 @@ +import { AuthSig, LIT_NETWORKS_KEYS } from '@lit-protocol/types'; + +import { StoredKeyMetadata } from '../types'; + +interface BaseApiParams { + sessionSig: AuthSig; + litNetwork: LIT_NETWORKS_KEYS; +} + +export type FetchKeyParams = BaseApiParams; + +export type SupportedNetworks = Extract< + LIT_NETWORKS_KEYS, + 'cayenne' | 'manzano' | 'habanero' +>; + +export interface StoreKeyParams extends BaseApiParams { + storedKeyMetadata: Pick< + StoredKeyMetadata, + 'pkpAddress' | 'publicKey' | 'keyType' | 'dataToEncryptHash' | 'ciphertext' + >; +} + +export interface BaseRequestParams { + sessionSig: AuthSig; + method: 'GET' | 'POST'; + litNetwork: LIT_NETWORKS_KEYS; +} diff --git a/packages/wrapped-keys/src/lib/service-client/utils.ts b/packages/wrapped-keys/src/lib/service-client/utils.ts new file mode 100644 index 0000000000..d024cc9672 --- /dev/null +++ b/packages/wrapped-keys/src/lib/service-client/utils.ts @@ -0,0 +1,134 @@ +import { AuthSig, LIT_NETWORKS_KEYS } from '@lit-protocol/types'; +import { + uint8arrayFromString, + uint8ArrayToBase64, +} from '@lit-protocol/uint8arrays'; + +import { + LIT_SESSIONSIG_AUTHORIZATION_SCHEMA_PREFIX, + SERVICE_URL_BY_LIT_NETWORK, +} from './constants'; +import { BaseRequestParams, SupportedNetworks } from './types'; +import { getPkpAddressFromSessionSig } from '../utils'; + +function composeAuthHeader(sessionSig: AuthSig) { + const sessionSigUintArr = uint8arrayFromString(JSON.stringify(sessionSig)); + + return `${LIT_SESSIONSIG_AUTHORIZATION_SCHEMA_PREFIX}${uint8ArrayToBase64( + sessionSigUintArr + )}`; +} + +const supportedNetworks: SupportedNetworks[] = [ + 'cayenne', + 'manzano', + 'habanero', +]; + +function isSupportedLitNetwork( + litNetwork: LIT_NETWORKS_KEYS +): asserts litNetwork is SupportedNetworks { + // @ts-expect-error - This is an assert function; litNetwork by definition may be an invalid value + if (!supportedNetworks.includes(litNetwork)) { + throw new Error( + `Unsupported LitNetwork! (${supportedNetworks.join('|')}) are supported.` + ); + } +} + +function getServiceUrl({ sessionSig, method, litNetwork }: BaseRequestParams) { + isSupportedLitNetwork(litNetwork); + + if (method === 'POST') { + return SERVICE_URL_BY_LIT_NETWORK[litNetwork]; + } + + const pkpAddress = getPkpAddressFromSessionSig(sessionSig); + return `${SERVICE_URL_BY_LIT_NETWORK[litNetwork]}/${pkpAddress}`; +} + +export function getBaseRequestParams(requestParams: BaseRequestParams): { + initParams: RequestInit; + url: string; +} { + const { sessionSig, method, litNetwork } = requestParams; + + // NOTE: Although HTTP conventions use capitalized letters for header names + // Lambda backend events from API gateway receive all lowercased header keys + return { + url: getServiceUrl(requestParams), + initParams: { + method, + headers: { + 'Content-Type': 'application/json', + 'Lit-Network': litNetwork, + Authorization: composeAuthHeader(sessionSig), // As Base64 string to avoid escaping issues + }, + }, + }; +} + +/** + * This method gives us _either_ the `message` key from the backend error response _or_ the text of the response if + * it was not JSON formed. + * + * Under normal operations, the backend will return errors in JSON format + * + * However, because we can't be 100% sure that an error response actually came from our backend code rather than + * from interim infrastructure, we need to assume that we may be getting a generic error that is plain text. + * + * @param {Response} response The response we received from fetch() + * @returns {string} The error message from the response + */ +async function getResponseErrorMessage(response: Response): Promise { + try { + const parsedResponse = await response.json(); + if (parsedResponse.message) { + return parsedResponse.message as string; + } + return JSON.stringify(parsedResponse); + } catch (e) { + return response.text(); + } +} + +/** This method will give us the JSON parsed response if possible, otherwise the text of the response as a string + * Responses from the backend API should always be in JSON format + * However, some mis-behaving infrastructure could return a 200 OK response code, but with a text string in the body + * + * @param {Response} response The response we received from fetch() + * @returns {|string} The error message from the response + */ +async function getResponseJson(response: Response): Promise { + try { + return (await response.json()) as Promise; // NOTE: `await` here is necessary for errors to be caught by try{} + } catch (e) { + return await response.text(); + } +} + +export async function makeRequest({ + url, + init, +}: { + url: string; + init: RequestInit; +}) { + const response = await fetch(url, { ...init }); + + if (!response.ok) { + const errorMessage = await getResponseErrorMessage(response); + throw new Error(`Failed to make request for wrapped key: ${errorMessage}`); + } + + /** + * + */ + const result = await getResponseJson(response); + + if (typeof result === 'string') { + throw new Error(`Unexpected response from wrapped key service: ${result}`); + } + + return result; +} diff --git a/packages/wrapped-keys/src/lib/types.ts b/packages/wrapped-keys/src/lib/types.ts new file mode 100644 index 0000000000..0f53555fc2 --- /dev/null +++ b/packages/wrapped-keys/src/lib/types.ts @@ -0,0 +1,188 @@ +import { + ILitNodeClient, + LIT_NETWORKS_KEYS, + SessionSigsMap, +} from '@lit-protocol/types'; + +/** @typedef Network + * The network type that the wrapped key will be used on. + */ +export type Network = 'evm' | 'solana'; +export type KeyType = 'K256' | 'ed25519'; + +/** All API calls for the wrapped keys service require these arguments. + * + * @typedef BaseApiParams + * @property {SessionSigsMap} pkpSessionSigs - The PKP sessionSigs used to associate the PKP with the generated private key and authenticate with the wrapped keys backend service. + * @property {ILitNodeClient} litNodeClient - The Lit Node Client used for executing the Lit Action and identifying which wrapped keys backend service to communicate with. + */ +export interface BaseApiParams { + pkpSessionSigs: SessionSigsMap; + litNodeClient: ILitNodeClient; +} + +export interface ApiParamsSupportedNetworks { + network: Network; +} + +/** Fetch a previously persisted key's metadata only requires valid pkpSessionSigs and a LIT Node Client instance configured for the appropriate network. + * + * @typedef GetEncryptedKeyMetadataParams + * @extends BaseApiParams + * + */ + +export type GetEncryptedKeyMetadataParams = BaseApiParams; + +/** Metadata for a key that has been stored, encrypted, on the wrapped keys backend service + * + * @property { string } ciphertext The base64 encoded, salted & encrypted private key + * @property { string } dataToEncryptHash SHA-256 of the ciphertext + * @property { string } publicKey The public key of the encrypted private key + * @property { string } pkpAddress The LIT PKP address that is associated with the encrypted private key + * @property { string } keyType The type of key that was encrypted -- e.g. ed25519, K256, etc. + * @property { LIT_NETWORKS_KEYS } litNetwork The LIT network that the client who stored the key was connected to + */ +export interface StoredKeyMetadata { + ciphertext: string; + dataToEncryptHash: string; + publicKey: string; + pkpAddress: string; + keyType: KeyType; + litNetwork: LIT_NETWORKS_KEYS; +} + +/** Fetching a previously persisted key's metadata only requires valid pkpSessionSigs and a LIT Node Client instance configured for the appropriate network. + * + * @typedef StoreEncryptedKeyMetadataParams + * @extends BaseApiParams + * + */ +export type StoreEncryptedKeyMetadataParams = BaseApiParams & + Pick< + StoredKeyMetadata, + 'publicKey' | 'keyType' | 'dataToEncryptHash' | 'ciphertext' + >; + +/** Exporting a previously persisted key only requires valid pkpSessionSigs and a LIT Node Client instance configured for the appropriate network. + * + * @typedef ExportPrivateKeyParams + * @extends BaseApiParams + * + */ +export type ExportPrivateKeyParams = BaseApiParams; + +/** Includes the decrypted private key and metadata that was stored alongside it in the wrapped keys service + * + * @typedef ExportPrivateKeyResult + * @property { LIT_NETWORKS_KEYS } litNetwork The LIT network that the LIT Node Client was configured for when the key was persisted to the wrapped keys service + * @property { string } decryptedPrivateKey The decrypted, plain text private key that was persisted to the wrapped keys service + * @property { string } pkpAddress The LIT PKP Address that the key was linked to; this is derived from the provided pkpSessionSigs + * @property { string } publicKey The public key of the key being imported into the wrapped keys service + * @property { string } keyType The algorithm type of the key; this might be K256, ed25519, or other key formats. The `keyType` will be included in the metadata returned from the wrapped keys service + * + */ +export interface ExportPrivateKeyResult { + pkpAddress: string; + decryptedPrivateKey: string; + publicKey: string; + litNetwork: LIT_NETWORKS_KEYS; + keyType: KeyType; +} + +/** @typedef GeneratePrivateKeyParams + * @extends BaseApiParams + * @property {Network} network The network for which the private key needs to be generated; keys are generated differently for different networks + */ +export type GeneratePrivateKeyParams = BaseApiParams & + ApiParamsSupportedNetworks; + +/** @typedef GeneratePrivateKeyResult + * @property { string } pkpAddress The LIT PKP Address that the key was linked to; this is derived from the provided pkpSessionSigs + * @property { string } generatedPublicKey The public key component of the newly generated keypair + * + */ +export interface GeneratePrivateKeyResult { + pkpAddress: string; + generatedPublicKey: string; +} + +/** @typedef ImportPrivateKeyParams + * @extends BaseApiParams + * + * @property { string } privateKey The private key to be imported into the wrapped keys service + * @property { string } publicKey The public key of the key being imported into the wrapped keys service + * @property { string } keyType The algorithm type of the key; this might be K256, ed25519, or other key formats. The `keyType` will be included in the metadata returned from the wrapped keys service + */ +export interface ImportPrivateKeyParams extends BaseApiParams { + privateKey: string; + publicKey: string; + keyType: KeyType; +} + +interface SignMessageParams { + messageToSign: string | Uint8Array; +} + +/** @typedef SignMessageWithEncryptedKeyParams + * @extends BaseApiParams + * + * @property { string | Uint8Array } messageToSign The message to be signed + */ +export type SignMessageWithEncryptedKeyParams = BaseApiParams & + ApiParamsSupportedNetworks & + SignMessageParams; + +interface BaseLitTransaction { + chain: string; +} + +/** EthereumLitTransaction must be provided to the `SignTransaction` endpoint when `network` is `evm`. + * + * @typedef EthereumLitTransaction + * + * @property { string } toAddress The address the transaction is 'to' + * @property { string } value The value of the transaction to be sent + * @property { number } chainId The chain ID of the target chain that the transaction will be executed on + * @property { string } [gasPrice] The exact gas price that you are willing to pay to execute the transaction + * @property { string } [gasLimit] The maximum gas price that you are willing to pay to execute the transaction + * @property { string } [dataHex] Data in hex format to be included in the transaction + * + */ +export interface EthereumLitTransaction extends BaseLitTransaction { + toAddress: string; + value: string; + chainId: number; + gasPrice?: string; + gasLimit?: number; + dataHex?: string; +} + +export interface SerializedTransaction extends BaseLitTransaction { + serializedTransaction: string; +} + +export interface SignTransactionParams extends BaseApiParams { + broadcast: boolean; +} + +export interface SignTransactionParamsSupportedEvm + extends SignTransactionParams { + unsignedTransaction: EthereumLitTransaction; + network: Extract; +} + +export interface SignTransactionParamsSupportedSolana + extends SignTransactionParams { + unsignedTransaction: SerializedTransaction; + network: Extract; +} + +/** @typedef SignTransactionWithEncryptedKeyParams + * @extends BaseApiParams + * @property { boolean } broadcast Whether the LIT action should broadcast the signed transaction to RPC, or only sign the transaction and return the signed transaction to the caller + * @property { EthereumLitTransaction | SerializedTransaction } unsignedTransaction The unsigned transaction to be signed. When network is 'solana', be sure to provide a {@link SerializedTransaction} instance. + */ +export type SignTransactionWithEncryptedKeyParams = + | SignTransactionParamsSupportedEvm + | SignTransactionParamsSupportedSolana; diff --git a/packages/wrapped-keys/src/lib/wrapped-keys.spec.ts b/packages/wrapped-keys/src/lib/utils.spec.ts similarity index 99% rename from packages/wrapped-keys/src/lib/wrapped-keys.spec.ts rename to packages/wrapped-keys/src/lib/utils.spec.ts index cbf1461795..24dfe55b4f 100644 --- a/packages/wrapped-keys/src/lib/wrapped-keys.spec.ts +++ b/packages/wrapped-keys/src/lib/utils.spec.ts @@ -3,12 +3,13 @@ import { SessionKeySignedMessage, SessionSigsMap, } from '@lit-protocol/types'; + +import { CHAIN_ETHEREUM } from './constants'; import { getFirstSessionSig, getPkpAccessControlCondition, getPkpAddressFromSessionSig, } from './utils'; -import { CHAIN_ETHEREUM } from './constants'; describe('getFirstSessionSig from sessionSigs record', () => { const sessionSigs: SessionSigsMap = { diff --git a/packages/wrapped-keys/src/lib/utils.ts b/packages/wrapped-keys/src/lib/utils.ts index ae2a9aff04..4a5727d207 100644 --- a/packages/wrapped-keys/src/lib/utils.ts +++ b/packages/wrapped-keys/src/lib/utils.ts @@ -1,39 +1,36 @@ +import { ethers } from 'ethers'; + +import { log } from '@lit-protocol/misc'; import { - AccessControlConditions, + AccsDefaultParams, AuthSig, - ExecuteJsResponse, SessionKeySignedMessage, SessionSigsMap, } from '@lit-protocol/types'; -import { log, logError } from '@lit-protocol/misc'; -import { CHAIN_ETHEREUM, ENCRYPTED_PRIVATE_KEY_ENDPOINT } from './constants'; -import { ethers } from 'ethers'; -import { - ExportPrivateKeyResponse, - ImportPrivateKeyResponse, - StoreToDatabaseParams, -} from './interfaces'; + +import { CHAIN_ETHEREUM } from './constants'; /** * * Extracts the first SessionSig from the SessionSigsMap since we only pass a single SessionSig to the AWS endpoint * - * @param pkpSessionSigs - The PKP sessionSigs (map) used to associated the PKP with the generated private key + * @param pkpSessionSigs - The PKP sessionSigs (map) used to associate the PKP with the generated private key * * @returns { AuthSig } - The first SessionSig from the map */ export function getFirstSessionSig(pkpSessionSigs: SessionSigsMap): AuthSig { - const keys = Object.keys(pkpSessionSigs); - if (keys.length === 0) { + const sessionSigsEntries = Object.entries(pkpSessionSigs); + + if (sessionSigsEntries.length === 0) { throw new Error( `Invalid pkpSessionSigs, length zero: ${JSON.stringify(pkpSessionSigs)}` ); } - const firstSessionSig: AuthSig = pkpSessionSigs[keys[0]]; - log(`Session Sig being used: ${JSON.stringify(firstSessionSig)}`); + const [[, sessionSig]] = sessionSigsEntries; + log(`Session Sig being used: ${JSON.stringify(sessionSig)}`); - return firstSessionSig; + return sessionSig; } /** @@ -50,188 +47,53 @@ export function getPkpAddressFromSessionSig(pkpSessionSig: AuthSig): string { ); const capabilities = sessionSignedMessage.capabilities; - if (capabilities.length > 3) { + + if (!capabilities || capabilities.length === 0) { throw new Error( - `At max 3 elements can be in the capabilities array but there are: ${capabilities.length}` + `Capabilities in the session's signedMessage is empty, but required.` ); } - for (const innerAuthSig of capabilities) { - const delegationAuthSig: AuthSig = JSON.parse(JSON.stringify(innerAuthSig)); // Had to stringify as it was throwing SyntaxError: "[object Object]" is not valid JSON - - if (delegationAuthSig.algo !== 'LIT_BLS') { - continue; - } + const delegationAuthSig = capabilities.find(({ algo }) => algo === 'LIT_BLS'); - const pkpAddress = delegationAuthSig.address; - - log(`pkpAddress to permit decryption: ${pkpAddress}`); - - return pkpAddress; + if (!delegationAuthSig) { + throw new Error( + 'SessionSig is not from a PKP; no LIT_BLS capabilities found' + ); } - throw new Error('SessionSig is not from a PKP'); + const pkpAddress = delegationAuthSig.address; + log(`pkpAddress to permit decryption: ${pkpAddress}`); + + return pkpAddress; } /** * * Creates the access control condition used to gate the access for Wrapped Key decryption * - * @param pkpAddress - The wallet address of the PKP which can decrypt the encrypted Wrapped Key + * @param { string } pkpAddress - The wallet address of the PKP which can decrypt the encrypted Wrapped Key * - * @returns { AccessControlConditions } - The access control condition that only allows the PKP address to decrypt + * @returns { AccsDefaultParams } - The access control condition that only allows the PKP address to decrypt */ export function getPkpAccessControlCondition( pkpAddress: string -): AccessControlConditions { +): AccsDefaultParams { if (!ethers.utils.isAddress(pkpAddress)) { throw new Error( `pkpAddress is not a valid Ethereum Address: ${pkpAddress}` ); } - return [ - { - contractAddress: '', - standardContractType: '', - chain: CHAIN_ETHEREUM, - method: '', - parameters: [':userAddress'], - returnValueTest: { - comparator: '=', - value: pkpAddress, - }, + return { + contractAddress: '', + standardContractType: '', + chain: CHAIN_ETHEREUM, + method: '', + parameters: [':userAddress'], + returnValueTest: { + comparator: '=', + value: pkpAddress, }, - ]; -} - -/** - * - * Extracts the first SessionSig item from the map and uses it to fetch the stored database item - * - * @param pkpSessionSigs - The PKP which is used to fetch the DynamoDB item - * - * @returns { ExportPrivateKeyResponse } - The DynamoDB item with all its attributes - */ -export async function fetchPrivateKeyMedataFromDatabase( - pkpSessionSigs: SessionSigsMap -): Promise { - const firstSessionSig = getFirstSessionSig(pkpSessionSigs); - - try { - const response = await fetch(ENCRYPTED_PRIVATE_KEY_ENDPOINT, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - pkpsessionsig: JSON.stringify(firstSessionSig), - }, - }); - - if (!response.ok) { - const errorBody = await response.text(); - logError( - `Could not fetch the encrypted key due to the error: ${errorBody}` - ); - - throw new Error(errorBody); - } - - return await response.json(); - } catch (error) { - const errorMessage = `There was a problem fetching from the database: ${error}`; - console.error(errorMessage); - - throw new Error(errorMessage); - } -} - -/** - * - * Store the encrypted private key into the database - * - * @param data - The encrypted data to be stored in the database (ciphertext, dataToEncryptHash) - * @param pkpSessionSigs - The PKP which is used to fetch the DynamoDB item - * - * @returns { ImportPrivateKeyResponse } - The PKP EthAddress of the associated PKP - */ -export async function storePrivateKeyMetadataToDatabase( - data: StoreToDatabaseParams, - firstSessionSig: AuthSig -): Promise { - try { - const response = await fetch(ENCRYPTED_PRIVATE_KEY_ENDPOINT, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - pkpsessionsig: JSON.stringify(firstSessionSig), - }, - body: JSON.stringify(data), - }); - - if (!response.ok) { - const errorBody = await response.text(); - logError( - `Could not import the encrypted key due to the error: ${errorBody}` - ); - - throw new Error(errorBody); - } - - return await response.json(); - } catch (error) { - const errorMessage = `There was a problem fetching from the database: ${error}`; - console.error(errorMessage); - - throw new Error(errorMessage); - } -} - -/** - * - * Post processes the Lit Action result to ensure that the result is non-empty and a valid string - * - * @param result - The Lit Action result to be processes - * - * @returns { string } - The response field in the Lit Action result object - */ -export function postLitActionValidation( - result: ExecuteJsResponse | undefined -): string { - // console.log(`Lit Action result: ${JSON.stringify(result)}`); - - if (!result) { - throw new Error('There was some error running the Lit Action'); - } - - const response = result.response; - // console.log('response'); - // console.log(response); - - if (!response) { - throw new Error( - `Expected "response" in Lit Action result: ${JSON.stringify(result)}` - ); - } - - if (typeof response !== 'string') { - // As the return value is a hex string - throw new Error( - `Lit Action should return a string response: ${JSON.stringify(result)}` - ); - } - - if (!result.success) { - throw new Error(`Expected "success" in res: ${JSON.stringify(result)}`); - } - - if (result.success !== true) { - throw new Error(`Expected "success" to be true: ${JSON.stringify(result)}`); - } - - if (response.startsWith('Error:')) { - // Lit Action sets an error response - throw new Error(`Error executing the Signing Lit Action: ${response}`); - } - - return response; + }; } diff --git a/packages/wrapped-keys/src/lib/wrapped-keys.ts b/packages/wrapped-keys/src/lib/wrapped-keys.ts deleted file mode 100644 index 8ef40226db..0000000000 --- a/packages/wrapped-keys/src/lib/wrapped-keys.ts +++ /dev/null @@ -1,485 +0,0 @@ -import { - CHAIN_ETHEREUM, - ENCRYPTED_PRIVATE_KEY_ENDPOINT, - LIT_ACTION_CID_REPOSITORY, - LIT_PREFIX, - NETWORK_SOLANA, -} from './constants'; -import { decryptToString, encryptString } from '@lit-protocol/encryption'; -import { logError } from '@lit-protocol/misc'; -import { - fetchPrivateKeyMedataFromDatabase, - getFirstSessionSig, - getPkpAccessControlCondition, - getPkpAddressFromSessionSig, - postLitActionValidation, - storePrivateKeyMetadataToDatabase, -} from './utils'; -import { - LitTransaction, - ExportPrivateKeyParams, - ExportPrivateKeyResponse, - ImportPrivateKeyParams, - SignTransactionWithEncryptedKeyParams, - SignMessageWithEncryptedKeyParams, - GeneratePrivateKeyParams, - GeneratePrivateKeyResponse, - CustomGeneratePrivateKeyParams, - CustomSignMessageWithEncryptedKeyParams, - CustomSignTransactionWithEncryptedKeyParams, -} from './interfaces'; - -/** - * - * Generates a random Solana/EVM private key inside the corresponding Lit Action and returns the publicKey of the random private key. We don't return the generated wallet address since it can be derived from the publicKey - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param network - The network for which the private key needs to be generated. This is used to call different Lit Actions since the keys will be of different types - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The publicKey of the generated random private key along with the PKP EthAddres associated with the Wrapped Key - */ -export async function generatePrivateKey({ - pkpSessionSigs, - network, - litNodeClient, -}: GeneratePrivateKeyParams): Promise { - const firstSessionSig = getFirstSessionSig(pkpSessionSigs); - const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); - const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); - console.log( - 'accessControlConditions: ', - JSON.stringify(allowPkpAddressToDecrypt) - ); - - const ipfsId = - network === NETWORK_SOLANA - ? LIT_ACTION_CID_REPOSITORY.generateEncryptedSolanaPrivateKey - : LIT_ACTION_CID_REPOSITORY.generateEncryptedEthereumPrivateKey; - - let ciphertext, dataToEncryptHash, publicKey; - try { - const result = await litNodeClient.executeJs({ - sessionSigs: pkpSessionSigs, - ipfsId, - jsParams: { - pkpAddress, - accessControlConditions: allowPkpAddressToDecrypt, - }, - }); - - const response = postLitActionValidation(result); - ({ ciphertext, dataToEncryptHash, publicKey } = JSON.parse(response)); - } catch (err: any) { - throw new Error( - `Lit Action threw an unexpected error: ${JSON.stringify(err)}` - ); - } - - const data = { ciphertext, dataToEncryptHash }; - - const importedPrivateKey = await storePrivateKeyMetadataToDatabase( - data, - firstSessionSig - ); - return { - pkpAddress: importedPrivateKey.pkpAddress, - generatedPublicKey: publicKey, - }; -} - -/** - * - * Generates a random private key inside the provided Lit Action and returns the publicKey of the random private key. - * Lit Action should bundle the required wallet packages and encrypt the private key after prepending "lit_" to it. - * Access control condition should only allow the PKP Eth address of the provided PKP sessionSigs to decrypt. - * Lit Action should return a stringified JSON with ciphertext, dataToEncryptHash, publicKey. - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param litActionIpfsCid - The IPFS CID of the Lit Action to be executed for generating the Wrapped Key. Can't provide this if already provided litActionCode - * @param litActionCode - The Lit Action code to be executed for generating the Wrapped Key. Can't provide this if already provided litActionIpfsCid - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The publicKey of the generated random private key along with the PKP EthAddres associated with the Wrapped Key - */ -export async function customGeneratePrivateKey({ - pkpSessionSigs, - litActionIpfsCid, - litActionCode, - litNodeClient, -}: CustomGeneratePrivateKeyParams): Promise { - if (!litActionIpfsCid && !litActionCode) { - throw new Error( - 'Have to provide either the litActionIpfsCid or litActionCode' - ); - } - - if (litActionIpfsCid && litActionCode) { - throw new Error("Can't provide both the litActionIpfsCid or litActionCode"); - } - - const firstSessionSig = getFirstSessionSig(pkpSessionSigs); - const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); - const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); - console.log( - 'accessControlConditions: ', - JSON.stringify(allowPkpAddressToDecrypt) - ); - - let ciphertext, dataToEncryptHash, publicKey; - try { - const result = await litNodeClient.executeJs({ - sessionSigs: pkpSessionSigs, - ipfsId: litActionIpfsCid, - code: litActionCode, - jsParams: { - pkpAddress, - accessControlConditions: allowPkpAddressToDecrypt, - }, - }); - - const response = postLitActionValidation(result); - ({ ciphertext, dataToEncryptHash, publicKey } = JSON.parse(response)); - } catch (err: any) { - throw new Error( - `Lit Action threw an unexpected error: ${JSON.stringify(err)}` - ); - } - - const data = { ciphertext, dataToEncryptHash }; - - const importedPrivateKey = await storePrivateKeyMetadataToDatabase( - data, - firstSessionSig - ); - return { - pkpAddress: importedPrivateKey.pkpAddress, - generatedPublicKey: publicKey, - }; -} - -/** - * - * Import any provided private key into our DynamoDB instance. First the key is pre-pended with LIT_PREFIX for security reasons. Then the updated key is encrypted and stored in the database - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param privateKey - The private key imported into the database - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The PKP EthAddres associated with the Wrapped Key - */ -export async function importPrivateKey({ - pkpSessionSigs, - privateKey, - litNodeClient, -}: ImportPrivateKeyParams): Promise { - const firstSessionSig = getFirstSessionSig(pkpSessionSigs); - const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); - const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); - - const updatedPrivateKey = LIT_PREFIX + privateKey; - - const { ciphertext, dataToEncryptHash } = await encryptString( - { - accessControlConditions: allowPkpAddressToDecrypt, - dataToEncrypt: updatedPrivateKey, - }, - litNodeClient - ); - - const data = { - ciphertext, - dataToEncryptHash, - }; - - const importedPrivateKey = await storePrivateKeyMetadataToDatabase( - data, - firstSessionSig - ); - return importedPrivateKey.pkpAddress; -} - -/** - * - * Exports any imported private key. First the stored encrypted private key is fetched from the database. Then it's decrypted and returned to the user - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param privateKey - The private key imported into the database - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The bare private key which was imported without any prefix - */ -export async function exportPrivateKey({ - pkpSessionSigs, - litNodeClient, -}: ExportPrivateKeyParams): Promise { - const firstSessionSig = getFirstSessionSig(pkpSessionSigs); - const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); - const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpAddress); - - let exportedPrivateKeyData: ExportPrivateKeyResponse; - - try { - const response = await fetch(ENCRYPTED_PRIVATE_KEY_ENDPOINT, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - pkpsessionsig: JSON.stringify(firstSessionSig), - }, - }); - - if (!response.ok) { - const errorBody = await response.text(); - logError( - `Could not fetch the encrypted key due to the error: ${errorBody}` - ); - - throw new Error(errorBody); - } - - exportedPrivateKeyData = await response.json(); - } catch (error) { - const errorMessage = `There was a problem fetching from the database: ${error}`; - console.error(errorMessage); - - throw new Error(errorMessage); - } - - const decryptedPrivateKey = await decryptToString( - { - accessControlConditions: allowPkpAddressToDecrypt, - chain: CHAIN_ETHEREUM, - ciphertext: exportedPrivateKeyData.ciphertext, - dataToEncryptHash: exportedPrivateKeyData.dataToEncryptHash, - sessionSigs: pkpSessionSigs, - }, - litNodeClient - ); - - // It will be of the form lit_ - return decryptedPrivateKey.startsWith(LIT_PREFIX) - ? decryptedPrivateKey.slice(LIT_PREFIX.length) - : decryptedPrivateKey; -} - -/** - * - * Signs a transaction inside the Lit Action using the Solana/EVM key. First it fetches the encrypted key from database and then executes a Lit Action that signed the tx. - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param network - The network for which the private key needs to be generated. This is used to call different Lit Actions since the keys will be of different types - * @param unsignedTransaction - The unsigned transaction which will be signed inside the Lit Action. It can be of type LitTransaction - * @param broadcast - Flag used to determine whether the Lit Action should broadcast the signed transaction or only return the signed transaction - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - Either the signed Solana/EVM transaction which the user can use to broadcast themselves or the transaction hash or the broadcasted Solana/EVM transaction - */ -export async function signTransactionWithEncryptedKey({ - pkpSessionSigs, - network, - unsignedTransaction, - broadcast, - litNodeClient, -}: SignTransactionWithEncryptedKeyParams): Promise { - const { pkpAddress, ciphertext, dataToEncryptHash } = - await fetchPrivateKeyMedataFromDatabase(pkpSessionSigs); - - const ipfsId = - network === NETWORK_SOLANA - ? LIT_ACTION_CID_REPOSITORY.signTransactionWithSolanaEncryptedKey - : LIT_ACTION_CID_REPOSITORY.signTransactionWithEthereumEncryptedKey; - - let result; - try { - result = await litNodeClient.executeJs({ - sessionSigs: pkpSessionSigs, - ipfsId, - jsParams: { - pkpAddress, - ciphertext, - dataToEncryptHash, - unsignedTransaction, - broadcast, - accessControlConditions: getPkpAccessControlCondition(pkpAddress), - }, - }); - } catch (err: any) { - throw new Error( - `Lit Action threw an unexpected error: ${JSON.stringify(err)}` - ); - } - - return postLitActionValidation(result); -} - -/** - * - * Signs a transaction inside the provided Lit Action. First it fetches the encrypted key from database and then executes a Lit Action that signed the tx. - * Lit Action should bundle the required wallet packages and decrypt the private key which may be prepended with "lit_". - * It should create the corresponding wallet instance with the bundled package and sign the passed message with it. - * It should either return the signed transaction or the transaction hash of the broadcasted transaction. - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param litActionIpfsCid - The IPFS CID of the Lit Action to be executed for generating the Wrapped Key. Can't provide this if already provided litActionCode - * @param litActionCode - The Lit Action code to be executed for generating the Wrapped Key. Can't provide this if already provided litActionIpfsCid - * @param serializedTransaction - The unsigned transaction which will be signed inside the Lit Action. It should be a serialized unsigned transaction - * @param broadcast - Flag used to determine whether the Lit Action should broadcast the signed transaction or only return the signed transaction - * @param params - Any other params passes to the Lit Action - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The signed signed transaction or the transaction hash of the broadcasted transaction by the Wrapped Key - */ -export async function customSignTransactionWithEncryptedKey({ - pkpSessionSigs, - litActionIpfsCid, - litActionCode, - serializedTransaction, - broadcast, - params, - litNodeClient, -}: CustomSignTransactionWithEncryptedKeyParams): Promise { - if (!litActionIpfsCid && !litActionCode) { - throw new Error( - 'Have to provide either the litActionIpfsCid or litActionCode' - ); - } - - if (litActionIpfsCid && litActionCode) { - throw new Error("Can't provide both the litActionIpfsCid or litActionCode"); - } - - const { pkpAddress, ciphertext, dataToEncryptHash } = - await fetchPrivateKeyMedataFromDatabase(pkpSessionSigs); - - let result; - try { - result = await litNodeClient.executeJs({ - sessionSigs: pkpSessionSigs, - ipfsId: litActionIpfsCid, - code: litActionCode, - jsParams: { - pkpAddress, - ciphertext, - dataToEncryptHash, - serializedTransaction, - broadcast, - accessControlConditions: getPkpAccessControlCondition(pkpAddress), - ...params, - }, - }); - } catch (err: any) { - throw new Error( - `Lit Action threw an unexpected error: ${JSON.stringify(err)}` - ); - } - - return postLitActionValidation(result); -} - -/** - * - * Signs a message inside the Lit Action using the Solana/EVM key. First it fetches the encrypted key from database and then executes a Lit Action that signed the tx - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param network - The network for which the private key needs to be generated. This is used to call different Lit Actions since the keys will be of different types - * @param messageToSign - The unsigned message which will be signed inside the Lit Action - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The signed Solana/EVM message - */ -export async function signMessageWithEncryptedKey({ - pkpSessionSigs, - network, - messageToSign, - litNodeClient, -}: SignMessageWithEncryptedKeyParams): Promise { - const { pkpAddress, ciphertext, dataToEncryptHash } = - await fetchPrivateKeyMedataFromDatabase(pkpSessionSigs); - - const ipfsId = - network === NETWORK_SOLANA - ? LIT_ACTION_CID_REPOSITORY.signMessageWithSolanaEncryptedKey - : LIT_ACTION_CID_REPOSITORY.signMessageWithEthereumEncryptedKey; - - let result; - try { - result = await litNodeClient.executeJs({ - sessionSigs: pkpSessionSigs, - ipfsId, - jsParams: { - pkpAddress, - ciphertext, - dataToEncryptHash, - messageToSign, - accessControlConditions: getPkpAccessControlCondition(pkpAddress), - }, - }); - } catch (err: any) { - throw new Error( - `Lit Action threw an unexpected error: ${JSON.stringify(err)}` - ); - } - - return postLitActionValidation(result); -} - -/** - * - * Signs a message inside the provided Lit Action. First it fetches the encrypted key from database and then executes a Lit Action that signed the tx - * Lit Action should bundle the required wallet packages and decrypt the private key which may be prepended with "lit_". - * It should create the corresponding wallet instance with the bundled package and sign the passed message with it. - * It should return the signed message. - * - * @param pkpSessionSigs - The PKP sessionSigs used to associated the PKP with the generated private key - * @param litActionIpfsCid - The IPFS CID of the Lit Action to be executed for generating the Wrapped Key. Can't provide this if already provided litActionCode - * @param litActionCode - The Lit Action code to be executed for generating the Wrapped Key. Can't provide this if already provided litActionIpfsCid - * @param messageToSign - The unsigned message which will be signed inside the Lit Action - * @param params - Any other params passes to the Lit Action - * @param litNodeClient - The Lit Node Client used for executing the Lit Action - * - * @returns { Promise } - The signed message by the Wrapped Key - */ -export async function customSignMessageWithEncryptedKey({ - pkpSessionSigs, - litActionIpfsCid, - litActionCode, - messageToSign, - params, - litNodeClient, -}: CustomSignMessageWithEncryptedKeyParams): Promise { - if (!litActionIpfsCid && !litActionCode) { - throw new Error( - 'Have to provide either the litActionIpfsCid or litActionCode' - ); - } - - if (litActionIpfsCid && litActionCode) { - throw new Error("Can't provide both the litActionIpfsCid or litActionCode"); - } - - const { pkpAddress, ciphertext, dataToEncryptHash } = - await fetchPrivateKeyMedataFromDatabase(pkpSessionSigs); - - let result; - try { - result = await litNodeClient.executeJs({ - sessionSigs: pkpSessionSigs, - ipfsId: litActionIpfsCid, - code: litActionCode, - jsParams: { - pkpAddress, - ciphertext, - dataToEncryptHash, - messageToSign, - accessControlConditions: getPkpAccessControlCondition(pkpAddress), - ...params, - }, - }); - } catch (err: any) { - throw new Error( - `Lit Action threw an unexpected error: ${JSON.stringify(err)}` - ); - } - - return postLitActionValidation(result); -}