diff --git a/local-tests/test.ts b/local-tests/test.ts index c66998d30b..05b90855c4 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -109,6 +109,7 @@ import { testFailBatchGeneratePrivateKeysAtomic } from './tests/wrapped-keys/tes import { setLitActionsCodeToLocal } from './tests/wrapped-keys/util'; import { testUseEoaSessionSigsToRequestSingleResponse } from './tests/testUseEoaSessionSigsToRequestSingleResponse'; +import { testUseTriaAuthAndWrappedKeysSessionSigsGen } from './tests/testUseTriaAuthAndWrappedKeysSessionSigsGen'; // Use the current LIT action code to test against setLitActionsCodeToLocal(); @@ -174,6 +175,7 @@ setLitActionsCodeToLocal(); testUseEoaSessionSigsToEncryptDecryptFile, testUseEoaSessionSigsToEncryptDecryptZip, testUseEoaSessionSigsToRequestSingleResponse, + testUseTriaAuthAndWrappedKeysSessionSigsGen, }; const pkpSessionSigsTests = { diff --git a/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts new file mode 100644 index 0000000000..b65f3ae756 --- /dev/null +++ b/local-tests/tests/testUseTriaAuthAndWrappedKeysSessionSigsGen.ts @@ -0,0 +1,112 @@ +import { LitActionResource, LitPKPResource } from '@lit-protocol/auth-helpers'; +import { log } from '@lit-protocol/misc'; +import { LitAbility } from '@lit-protocol/types'; +import { + getLitActionSessionSigs, + getLitActionSessionSigsUsingIpfsId, +} from 'local-tests/setup/session-sigs/get-lit-action-session-sigs'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { api } from '@lit-protocol/wrapped-keys'; + +import Hash from 'typestub-ipfs-only-hash'; +import { AuthMethodScope } from '@lit-protocol/constants'; + +const { triaBatchGeneratePrivateKeys, exportPrivateKey } = api; +/** + * Test Commands: + * ✅ NETWORK=datil-dev yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen + * ✅ NETWORK=datil-test yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen + * ✅ NETWORK=datil yarn test:local --filter=testUseTriaAuthAndWrappedKeysSessionSigsGen + */ +export const testUseTriaAuthAndWrappedKeysSessionSigsGen = async ( + devEnv: TinnyEnvironment +) => { + const alice = await devEnv.createRandomPerson(); + + // -- Start + const triaAuthMethod = { + // authMethodId: '', <-- Tria's managing this by permitting auth method to the user id + authMethodType: process.env.TRIA_AUTHMETHOD_TYPE, + accessToken: process.env.TRIA_ACCESS_TOKEN, + }; + + // -- mint a pkp + console.log(`🔄 Minting new PKP...`); + const pkpMintRes = + await devEnv.contractsClient.pkpNftContractUtils.write.mint(); + const pkp = pkpMintRes.pkp; + console.log(` ✅ PKP minted:`); + console.log(` - Token ID: ${pkp.tokenId}`); + console.log(` - Public Key: ${pkp.publicKey}`); + console.log(` - ETH Address: ${pkp.ethAddress}`); + + // -- mint capacity token + console.log(`🔄 Minting Capacity Credits NFT...`); + const capacityTokenId = ( + await devEnv.contractsClient.mintCapacityCreditsNFT({ + requestsPerKilosecond: 10, + daysUntilUTCMidnightExpiration: 1, + }) + ).capacityTokenIdStr; + console.log(` ✅ Capacity Credits NFT minted:`); + + // -- create capacity delegation auth sig + console.log(`🔄 Creating Capacity Delegation AuthSig...`); + const authSigResponse = + await devEnv.litNodeClient.createCapacityDelegationAuthSig({ + dAppOwnerWallet: alice.wallet, + capacityTokenId, + delegateeAddresses: [pkp.ethAddress], + uses: '1', + }); + const capacityDelegationAuthSig = authSigResponse.capacityDelegationAuthSig; + console.log(` ✅ Capacity Delegation AuthSig created:`); + console.log(` - AuthSig: ${JSON.stringify(capacityDelegationAuthSig)}`); + console.log(` - Uses: 1`); + console.log(` - Delegatee Address: ${pkp.ethAddress}`); + console.log(` - Capacity Token ID: ${capacityTokenId}`); + + // -- Get the lit action code.. + const { litActionCode, litActionIpfsCid } = api.getLitActionCodeOrCidCommon( + 'triaAuthAndBatchGenerateEncryptedKeys' + ); + + // -- detect which one we got + const hashOfLitActionCode = litActionCode + ? await Hash.of(Buffer.from(litActionCode)) + : litActionIpfsCid; + console.log(` ✅ Lit Action Code IPFS CID: ${hashOfLitActionCode}`); + + console.log(`🔄 Adding permitted action...`); + const permitTx = await devEnv.contractsClient.addPermittedAction({ + ipfsId: hashOfLitActionCode, + pkpTokenId: pkp.tokenId, + authMethodScopes: [AuthMethodScope.SignAnything], + }); + console.log(` ✅ Permitted action added:`); + console.log(` - Transaction Hash: ${permitTx.transactionHash}`); + + const solanaMessageToSign = 'This is a test solana message'; + const evmMessageToSign = 'This is a test evm message'; + + const { results } = await triaBatchGeneratePrivateKeys({ + pkpPublicKey: pkp.publicKey, + ipfsId: hashOfLitActionCode, + actions: [ + { + network: 'evm', + signMessageParams: { messageToSign: evmMessageToSign }, + generateKeyParams: { memo: 'Test evm key' }, + }, + { + network: 'solana', + signMessageParams: { messageToSign: solanaMessageToSign }, + generateKeyParams: { memo: 'Test solana key' }, + }, + ], + litNodeClient: devEnv.litNodeClient, + authMethod: triaAuthMethod, + }); + + console.log('results:', results); +}; diff --git a/local-tests/tests/wrapped-keys/util.ts b/local-tests/tests/wrapped-keys/util.ts index 4f3573fe33..1a7db4b42c 100644 --- a/local-tests/tests/wrapped-keys/util.ts +++ b/local-tests/tests/wrapped-keys/util.ts @@ -15,6 +15,7 @@ import type { const emptyLitActionRepositoryCommon: LitActionCodeRepositoryCommon = { batchGenerateEncryptedKeys: '', + triaAuthAndBatchGenerateEncryptedKeys: '', }; const emptyLitActionRepository: LitActionCodeRepository = { diff --git a/package.json b/package.json index fad1755fd2..7a947b8eda 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "tslib": "^2.3.0", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", + "typestub-ipfs-only-hash": "^4.0.0", "uint8arrays": "^4.0.3" }, "devDependencies": { diff --git a/packages/lit-node-client-nodejs/src/lib/helpers/parseCustomResources.ts b/packages/lit-node-client-nodejs/src/lib/helpers/parseCustomResources.ts new file mode 100644 index 0000000000..db693eac99 --- /dev/null +++ b/packages/lit-node-client-nodejs/src/lib/helpers/parseCustomResources.ts @@ -0,0 +1,38 @@ +export function parseCustomResources(nodeResponses: any) { + return nodeResponses.values + .map((item: any) => { + return { + signedMessage: item.siweMessage, + }; + }) + .map((v: any, i: number) => { + const signedMessage = v.signedMessage; + const urnLine = signedMessage.match(/urn:recap:[\w\d]+/)![0]; + + const authContext = JSON.parse(atob(urnLine.split(':')[2])).att[ + 'lit-resolvedauthcontext://*' + ]['Auth/Auth'][0]['auth_context']; + + const extractedCustomAuthResource = authContext[ + 'customAuthResource' + ].slice(8, -2); + const customAuthResources = extractedCustomAuthResource.replace( + /\\"/g, + '"' + ); + let result; + + try { + result = JSON.parse(customAuthResources); + } catch (e) { + result = extractedCustomAuthResource; + } + + return { + customAuthResources: result, + // authContext, + }; + }) + .find((item: any) => item.customAuthResources !== 'undefined') + .customAuthResources; +} diff --git a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts index 858a46d065..8cd8038ed9 100644 --- a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts +++ b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts @@ -43,6 +43,7 @@ import { findMostCommonResponse, formatSessionSigs, hexPrefixed, + leastCommonString, log, logError, logErrorWithRequestId, @@ -76,6 +77,7 @@ import { parsePkpSignResponse } from './helpers/parse-pkp-sign-response'; import { processLitActionResponseStrategy } from './helpers/process-lit-action-response-strategy'; import { removeDoubleQuotes } from './helpers/remove-double-quotes'; import { blsSessionSigVerify } from './helpers/validate-bls-session-sig'; +import { parseCustomResources } from './helpers/parseCustomResources'; import type { AuthCallback, @@ -1880,18 +1882,35 @@ export class LitNodeClientNodeJs }); // -- resolve promises + const numberToResolve = params?.handleAllResponses + ? this.connectedNodes.size + : this.config.minNodeCount; + log( + `[signSessionKey] number of node promises to resolve:`, + numberToResolve + ); + let res; try { res = await this.handleNodePromises( nodePromises, requestId, - this.config.minNodeCount + numberToResolve ); log('signSessionKey node promises:', res); } catch (e) { throw new Error(`Error when handling node promises: ${e}`); } + // -- parse that custom thing + let customAuthResources; + + try { + customAuthResources = parseCustomResources(res); + } catch (e) { + log(`Failed to parse custom resources, not a problem.`); + } + logWithRequestId(requestId, 'handleNodePromises res:', res); // -- case: promises rejected @@ -1993,10 +2012,13 @@ export class LitNodeClientNodeJs ); } + const commonStringStrategy = + params?.strategy === 'mostCommon' ? mostCommonString : leastCommonString; + const blsSignedData: BlsResponseData[] = validatedSignedDataList as BlsResponseData[]; - const sigType = mostCommonString(blsSignedData.map((s) => s.curveType)); + const sigType = commonStringStrategy(blsSignedData.map((s) => s.curveType)); log(`[signSessionKey] sigType:`, sigType); const signatureShares = getBlsSignatures(blsSignedData); @@ -2013,10 +2035,12 @@ export class LitNodeClientNodeJs const publicKey = removeHexPrefix(params.pkpPublicKey); log(`[signSessionKey] publicKey:`, publicKey); - const dataSigned = mostCommonString(blsSignedData.map((s) => s.dataSigned)); + const dataSigned = commonStringStrategy( + blsSignedData.map((s) => s.dataSigned) + ); log(`[signSessionKey] dataSigned:`, dataSigned); - const mostCommonSiweMessage = mostCommonString( + const mostCommonSiweMessage = commonStringStrategy( blsSignedData.map((s) => s.siweMessage) ); @@ -2035,6 +2059,9 @@ export class LitNodeClientNodeJs derivedVia: 'lit.bls', signedMessage, address: computeAddress(hexPrefixed(publicKey)), + ...(customAuthResources && { + customAuthResources: customAuthResources, + }), }, pkpPublicKey: publicKey, }; @@ -2318,6 +2345,10 @@ export class LitNodeClientNodeJs litActionIpfsId: props.litActionIpfsId, }), ...(props.jsParams && { jsParams: props.jsParams }), + + ...(params.handleAllResponses && { + handleAllResponses: params.handleAllResponses, + }), }); return response.authSig; diff --git a/packages/misc/src/lib/misc.ts b/packages/misc/src/lib/misc.ts index e91d0b5f5b..813f4361a9 100644 --- a/packages/misc/src/lib/misc.ts +++ b/packages/misc/src/lib/misc.ts @@ -65,6 +65,23 @@ export const mostCommonString = (arr: Array): any => { .pop(); }; +/** + * + * Find the element that occurs the least in an array + * + * @param { Array } arr + * @returns { any } the element that appeared the least + */ +export const leastCommonString = (arr: Array): any => { + return arr + .sort( + (a: any, b: any) => + arr.filter((v: any) => v === b).length - + arr.filter((v: any) => v === a).length + ) + .pop(); +}; + export const findMostCommonResponse = (responses: Array): object => { const result: { [key: string]: any } = {}; diff --git a/packages/types/src/lib/ILitNodeClient.ts b/packages/types/src/lib/ILitNodeClient.ts index 0f8b3646b0..dcee100d72 100644 --- a/packages/types/src/lib/ILitNodeClient.ts +++ b/packages/types/src/lib/ILitNodeClient.ts @@ -18,6 +18,8 @@ import { RejectedNodePromises, SendNodeCommand, SuccessNodePromises, + GetLitActionSessionSigs, + SessionSigsMap, } from './interfaces'; import { ILitResource, ISessionCapabilityObject } from './models'; import { SupportedJsonRequests } from './types'; @@ -227,4 +229,15 @@ export interface ILitNodeClient { generateSessionCapabilityObjectWithWildcards( litResources: ILitResource[] ): Promise; + + /** + * Retrieves session signatures specifically for Lit Actions. + * Unlike `getPkpSessionSigs`, this function requires either `litActionCode` or `litActionIpfsId`, and `jsParams` must be provided. + * + * @param params - The parameters required for retrieving the session signatures. + * @returns A promise that resolves with the session signatures. + */ + getLitActionSessionSigs( + params: GetLitActionSessionSigs + ): Promise; } diff --git a/packages/types/src/lib/interfaces.ts b/packages/types/src/lib/interfaces.ts index d44c6162cc..80abaf72ec 100644 --- a/packages/types/src/lib/interfaces.ts +++ b/packages/types/src/lib/interfaces.ts @@ -1047,7 +1047,9 @@ export interface CreateCustomAuthMethodRequest { // pub auth_sig: Option, // pub siwe_message: String, // } -export interface SignSessionKeyProp extends LitActionSdkParams { +export interface SignSessionKeyProp + extends LitActionSdkParams, + RespondHandling { /** * The serialized session key pair to sign. If not provided, a session key pair will be fetched from localStorge or generated. */ @@ -1910,7 +1912,8 @@ export interface SignerLike { export interface GetPkpSessionSigs extends CommonGetSessionSigsProps, - LitActionSdkParams { + LitActionSdkParams, + RespondHandling { pkpPublicKey: string; /** @@ -1943,7 +1946,19 @@ export type GetLitActionSessionSigs = CommonGetSessionSigsProps & }) ) & { ipfsOptions?: IpfsOptions; - }; + } & RespondHandling; + +export interface RespondHandling { + /** + * Whether to handle all responses or threshold/minNodeCount responses + */ + handleAllResponses?: boolean; + + /** + * Strategy to handle responses + */ + strategy?: ResponseStrategy; +} export interface SessionKeyCache { value: SessionKeyPair; diff --git a/packages/wrapped-keys-lit-actions/esbuild.config.js b/packages/wrapped-keys-lit-actions/esbuild.config.js index 52e2d6f368..4e99ba3084 100644 --- a/packages/wrapped-keys-lit-actions/esbuild.config.js +++ b/packages/wrapped-keys-lit-actions/esbuild.config.js @@ -58,6 +58,7 @@ module.exports = { './src/lib/self-executing-actions/ethereum/generateEncryptedEthereumPrivateKey.js', './src/lib/self-executing-actions/common/exportPrivateKey.js', './src/lib/self-executing-actions/common/batchGenerateEncryptedKeys.js', + './src/lib/self-executing-actions/common/triaAuthAndBatchGenerateEncryptedKeys.js', ], bundle: true, minify: true, diff --git a/packages/wrapped-keys-lit-actions/src/index.ts b/packages/wrapped-keys-lit-actions/src/index.ts index 5e8f5427b0..2f51f80f2f 100644 --- a/packages/wrapped-keys-lit-actions/src/index.ts +++ b/packages/wrapped-keys-lit-actions/src/index.ts @@ -1,4 +1,5 @@ import * as batchGenerateEncryptedKeys from './generated/common/batchGenerateEncryptedKeys'; +import * as triaAuthAndBatchGenerateEncryptedKeys from './generated/common/triaAuthAndBatchGenerateEncryptedKeys'; import * as exportPrivateKey from './generated/common/exportPrivateKey'; import * as generateEncryptedEthereumPrivateKey from './generated/ethereum/generateEncryptedEthereumPrivateKey'; import * as signMessageWithEthereumEncryptedKey from './generated/ethereum/signMessageWithEncryptedEthereumKey'; @@ -34,6 +35,8 @@ const litActionRepository: LitActionCodeRepository = { const litActionRepositoryCommon: LitActionCodeRepositoryCommon = { batchGenerateEncryptedKeys: batchGenerateEncryptedKeys.code, + triaAuthAndBatchGenerateEncryptedKeys: + triaAuthAndBatchGenerateEncryptedKeys.code, }; export { @@ -43,6 +46,7 @@ export { // Individual exports to allow tree-shaking and only importing the lit actions you need batchGenerateEncryptedKeys, + triaAuthAndBatchGenerateEncryptedKeys, exportPrivateKey, generateEncryptedEthereumPrivateKey, signMessageWithEthereumEncryptedKey, diff --git a/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/common/triaAuthAndBatchGenerateEncryptedKeys.js b/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/common/triaAuthAndBatchGenerateEncryptedKeys.js new file mode 100644 index 0000000000..96ed7dda92 --- /dev/null +++ b/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/common/triaAuthAndBatchGenerateEncryptedKeys.js @@ -0,0 +1,248 @@ +const { encryptPrivateKey } = require('../../internal/common/encryptKey'); +const { + generateEthereumPrivateKey, +} = require('../../internal/ethereum/generatePrivateKey'); +const { + signMessageEthereumKey, +} = require('../../internal/ethereum/signMessage'); +const { + generateSolanaPrivateKey, +} = require('../../internal/solana/generatePrivateKey'); +const { signMessageSolanaKey } = require('../../internal/solana/signMessage'); + +async function processEthereumAction({ action, accessControlConditions }) { + const { network, generateKeyParams } = action; + const messageToSign = action.signMessageParams?.messageToSign; + + const ethereumKey = generateEthereumPrivateKey(); + + const [generatedPrivateKey, messageSignature] = await Promise.all([ + encryptPrivateKey({ + accessControlConditions, + publicKey: ethereumKey.publicKey, + privateKey: ethereumKey.privateKey, + }), + messageToSign + ? signMessageEthereumKey({ + messageToSign: messageToSign, + privateKey: ethereumKey.privateKey, + }) + : Promise.resolve(), + ]); + + return { + network, + generateEncryptedPrivateKey: { + ...generatedPrivateKey, + memo: generateKeyParams.memo, + }, + ...(messageSignature + ? { signMessage: { signature: messageSignature } } + : {}), + }; +} + +async function processSolanaAction({ action, accessControlConditions }) { + const { network, generateKeyParams } = action; + + const messageToSign = action.signMessageParams?.messageToSign; + + const solanaKey = generateSolanaPrivateKey(); + + const [generatedPrivateKey, messageSignature] = await Promise.all([ + encryptPrivateKey({ + accessControlConditions, + publicKey: solanaKey.publicKey, + privateKey: solanaKey.privateKey, + }), + messageToSign + ? signMessageSolanaKey({ + messageToSign: messageToSign, + privateKey: solanaKey.privateKey, + }) + : Promise.resolve(), + ]); + + return { + network, + generateEncryptedPrivateKey: { + ...generatedPrivateKey, + memo: generateKeyParams.memo, + }, + ...(messageSignature + ? { signMessage: { signature: messageSignature } } + : {}), + }; +} + +async function processActions({ actions, accessControlConditions }) { + return Promise.all( + actions.map(async (action, ndx) => { + const { network } = action; + + if (network === 'evm') { + return await processEthereumAction({ + action, + accessControlConditions, + }); + } else if (network === 'solana') { + return await processSolanaAction({ + action, + accessControlConditions, + }); + } else { + // Just in case :tm: + throw new Error(`Invalid network for action[${ndx}]: ${network}`); + } + }) + ); +} + +function validateActionParams(actions) { + if (!actions) { + throw new Error('Missing required field: actions'); + } + + if (!actions.length) { + throw new Error('No actions provided (empty array?)'); + } + + actions.forEach((action, ndx) => { + if (!['evm', 'solana'].includes(action.network)) { + throw new Error( + `Invalid field: actions[${ndx}].network: ${action.network}` + ); + } + + if (!action.generateKeyParams) { + throw new Error( + `Missing required field: actions[${ndx}].generateKeyParams` + ); + } + + if (!action.generateKeyParams?.memo) { + throw new Error( + `Missing required field: actions[${ndx}].generateKeyParams.memo` + ); + } + + if (action.signMessageParams && !action.signMessageParams?.messageToSign) { + throw new Error( + `Missing required field: actions[${ndx}].signMessageParams.messageToSign` + ); + } + }); +} + +function validateTriaParams(triaParams) { + if (!triaParams.authMethod) { + throw new Error('Missing required field: authMethod'); + } + if (!triaParams.publicKey) { + throw new Error('Missing required field: publicKey'); + } + const { accessToken, authMethodType } = triaParams.authMethod; + + if (!accessToken) { + throw new Error('Missing required field: authMethod.accessToken'); + } + if (!authMethodType) { + throw new Error('Missing required field: authMethod.authMethodType'); + } +} + +async function triaAuth({ accessToken, publicKey, authMethodType }) { + // -- Authentication + const url = 'https://api.development.tria.so/api/v1/user/info'; + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }); + const data = await response.json(); + console.log('data', data); + + if (!data.success) { + throw new Error(`Authentication Failed`); + } + + // -- Authorization + // -- 1. get the authMethodId from unique identify from the response + const authMethodId = `${ethers.utils.keccak256( + ethers.utils.toUtf8Bytes(data.userInfo.uuid) + )}`; + console.log('Computed AuthMethodId', authMethodId); + + // -- 2. get the PKP token id + const tokenId = Lit.Actions.pubkeyToTokenId({ + publicKey: publicKey, + }); + console.log('tokenId', tokenId); + + // -- 3. get the permitted auth methods of the PKP token id + const permittedAuthMethods = await Lit.Actions.getPermittedAuthMethods({ + tokenId, + }); + console.log('permittedAuthMethods', permittedAuthMethods); + + // -- 4. only get where authMethod that's equal to the authMethod Id + const permittedAuthMethod = permittedAuthMethods.find( + (method) => method.id === authMethodId + ); + console.log('permittedAuthMethod', permittedAuthMethod); + + // TODO: Uncomment this block to enable Authorization + // Authorization:: Failed Authentication and Authorization + // if ( + // !permittedAuthMethod || + // permittedAuthMethod.auth_method_type !== jsParams.authMethod.authMethodType + // ) { + // Lit.Actions.setResponse({ + // response: JSON.stringify({ + // success: false, + // message: 'Authorization Failed', + // }), + // }); + // return; + // } + + return { + success: true, + message: 'Authentication and Authorization successful', + authMethodId, + }; +} + +export async function triaAuthAndBatchGenerateEncryptedKeys({ + actions, + accessControlConditions, + triaParams, +}) { + validateActionParams(actions); + validateTriaParams(triaParams); + + // -- Authenticate and authorize with Tria + await triaAuth({ + accessToken: triaParams.authMethod.accessToken, + authMethodType: triaParams.authMethod.authMethodType, + publicKey: triaParams.publicKey, + }); + + // -- Run once + let res = await Lit.Actions.runOnce( + { waitForResponse: false, name: 'tria-auth-and-wrapped-keys' }, + async () => { + const processedActions = await processActions({ + actions, + accessControlConditions, + }); + return JSON.stringify(processedActions); + } + ); + + return JSON.stringify(`(true, ${res})`); + // 1. Generate both EVM and solana private keys + // 2. Run appropriate signMessage for each key _and_ encrypt the keys for persistence to wrapped-keys backend + // 3. Return results for both signMessage ops and both encrypted key payloads for persistence +} diff --git a/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/index.js b/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/index.js index f5c88f070d..83a2fbc44b 100644 --- a/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/index.js +++ b/packages/wrapped-keys-lit-actions/src/lib/raw-action-functions/index.js @@ -1,6 +1,9 @@ const { batchGenerateEncryptedKeys, } = require('./common/batchGenerateEncryptedKeys'); +const { + triaAuthAndBatchGenerateEncryptedKeys, +} = require('./common/triaAuthAndBatchGenerateEncryptedKeys'); const { exportPrivateKey } = require('./common/exportPrivateKey'); const { generateEncryptedEthereumPrivateKey, @@ -24,6 +27,7 @@ const { export const rawActionFunctions = { exportPrivateKey, batchGenerateEncryptedKeys, + triaAuthAndBatchGenerateEncryptedKeys, generateEncryptedEthereumPrivateKey, signMessageWithEncryptedEthereumKey, signTransactionWithEncryptedEthereumKey, diff --git a/packages/wrapped-keys-lit-actions/src/lib/self-executing-actions/common/triaAuthAndBatchGenerateEncryptedKeys.js b/packages/wrapped-keys-lit-actions/src/lib/self-executing-actions/common/triaAuthAndBatchGenerateEncryptedKeys.js new file mode 100644 index 0000000000..5905bd7f20 --- /dev/null +++ b/packages/wrapped-keys-lit-actions/src/lib/self-executing-actions/common/triaAuthAndBatchGenerateEncryptedKeys.js @@ -0,0 +1,12 @@ +import { litActionHandler } from '../../litActionHandler'; +import { triaAuthAndBatchGenerateEncryptedKeys } from '../../raw-action-functions/common/triaAuthAndBatchGenerateEncryptedKeys'; + +/* global actions accessControlConditions triaParams*/ +(async () => + litActionHandler(async () => + triaAuthAndBatchGenerateEncryptedKeys({ + actions, + accessControlConditions, + triaParams, + }) + ))(); diff --git a/packages/wrapped-keys/src/index.ts b/packages/wrapped-keys/src/index.ts index 88312d4671..9943cb55a9 100644 --- a/packages/wrapped-keys/src/index.ts +++ b/packages/wrapped-keys/src/index.ts @@ -9,6 +9,7 @@ import { listEncryptedKeyMetadata, batchGeneratePrivateKeys, storeEncryptedKeyBatch, + triaBatchGeneratePrivateKeys, } from './lib/api'; import { CHAIN_ETHEREUM, @@ -27,6 +28,7 @@ import { LitActionCodeRepositoryCommon, LitActionCodeRepositoryEntry, } from './lib/lit-actions-client/types'; +import { getLitActionCodeOrCidCommon } from './lib/lit-actions-client/utils'; import type { SupportedNetworks } from './lib/service-client/types'; import type { @@ -75,6 +77,8 @@ export const api = { storeEncryptedKey, storeEncryptedKeyBatch, batchGeneratePrivateKeys, + triaBatchGeneratePrivateKeys, + getLitActionCodeOrCidCommon, }; export const config = { diff --git a/packages/wrapped-keys/src/lib/api/index.ts b/packages/wrapped-keys/src/lib/api/index.ts index 2eebfbfc57..d332838267 100644 --- a/packages/wrapped-keys/src/lib/api/index.ts +++ b/packages/wrapped-keys/src/lib/api/index.ts @@ -1,4 +1,5 @@ import { batchGeneratePrivateKeys } from './batch-generate-private-keys'; +import { triaBatchGeneratePrivateKeys } from './tria-batch-generate-private-keys'; import { exportPrivateKey } from './export-private-key'; import { generatePrivateKey } from './generate-private-key'; import { getEncryptedKey } from './get-encrypted-key'; @@ -20,4 +21,5 @@ export { storeEncryptedKeyBatch, getEncryptedKey, batchGeneratePrivateKeys, + triaBatchGeneratePrivateKeys, }; diff --git a/packages/wrapped-keys/src/lib/api/tria-batch-generate-private-keys.ts b/packages/wrapped-keys/src/lib/api/tria-batch-generate-private-keys.ts new file mode 100644 index 0000000000..e56a3dc184 --- /dev/null +++ b/packages/wrapped-keys/src/lib/api/tria-batch-generate-private-keys.ts @@ -0,0 +1,146 @@ +import { + getFirstSessionSig, + getKeyTypeFromNetwork, + getPkpAccessControlCondition, + getPkpAddressFromSessionSig, +} from './utils'; +import { batchGenerateKeysWithLitAction } from '../lit-actions-client'; +import { getLitActionCodeOrCidCommon } from '../lit-actions-client/utils'; +import { + LitAbility, + LitActionResource, + LitPKPResource, +} from '@lit-protocol/auth-helpers'; +import { storePrivateKeyBatch } from '../service-client'; +import { + BatchGeneratePrivateKeysActionResult, + BatchGeneratePrivateKeysParams, + BatchGeneratePrivateKeysResult, +} from '../types'; +import { computeAddress } from 'ethers/lib/utils'; +import { SessionSigsMap } from '@lit-protocol/types'; + +/** + * Generates a batch of private keys and optionally signs messages. + * + * @param {Object} params - Parameters for generating keys and signing messages. + * @param {string} params.pkpPublicKey - The public key for the PKP (e.g., "0x123..."). + * @param {string} params.ipfsId - The IPFS ID (e.g., "Qm..."). + * @param {Object} params.authMethod - The authentication method. + * @param {string} params.authMethod.authMethodType - The type of authentication method (e.g., "0x..."). + * @param {string} params.authMethod.accessToken - The access token (e.g., "eyJ..."). + * @param {Object} params.litNodeClient - The Lit Node client instance. + * @param {Array} params.actions - The actions to perform. + * + * @returns {Promise} - The generated keys and optionally signed messages. + * + * @throws {Error} - Throws an error if required parameters are missing or if the Lit Action Session Sigs cannot be retrieved. + */ +export async function triaBatchGeneratePrivateKeys( + params: Omit & { + pkpPublicKey: string | `0x${string}`; + ipfsId: string | `Qm${string}`; + authMethod: { + authMethodType: string | `0x${string}`; + accessToken: string | `eyJ${string}`; + }; + } +): Promise { + if (!params.litNodeClient) { + throw new Error(`Error: litNodeClient is required`); + } + if (!params.pkpPublicKey) { + throw new Error(`Error: pkpPublicKey is required`); + } + if (!params.ipfsId) { + throw new Error(`Error: ipfsId is required`); + } + + let pkpPubKey = params.pkpPublicKey.startsWith('0x') + ? params.pkpPublicKey.slice(2) + : params.pkpPublicKey; + + const pkpPubkeyBuffer = Buffer.from(pkpPubKey, 'hex'); + const pkpEthAddress = computeAddress(pkpPubkeyBuffer); + const allowPkpAddressToDecrypt = getPkpAccessControlCondition(pkpEthAddress); + + let litActionSessionSigs: SessionSigsMap; + + const _jsParams = { + triaParams: { + authMethod: { + accessToken: params.authMethod.accessToken, + authMethodType: params.authMethod.authMethodType, + }, + publicKey: pkpPubKey, + }, + actions: params.actions, + accessControlConditions: [allowPkpAddressToDecrypt], + }; + + try { + litActionSessionSigs = await params.litNodeClient.getLitActionSessionSigs({ + expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), + pkpPublicKey: params.pkpPublicKey, + resourceAbilityRequests: [ + { + resource: new LitPKPResource('*'), + ability: LitAbility.PKPSigning, + }, + { + resource: new LitActionResource('*'), + ability: LitAbility.LitActionExecution, + }, + ], + litActionIpfsId: params.ipfsId, + jsParams: _jsParams, + handleAllResponses: true, + strategy: 'leastCommon', + }); + } catch (e: any) { + throw new Error(`Error getting Lit Action Session Sigs: ${e.message}`); + } + + const firstSessionSig = Object.entries(litActionSessionSigs)[0][1]; + const firstSignedMessage = JSON.parse(firstSessionSig.signedMessage); + const firstCapabilities = firstSignedMessage.capabilities[0]; + const theCustomAuthResources = firstCapabilities.customAuthResources; + const pkpAddress = getPkpAddressFromSessionSig(firstSessionSig); + + const keyParamsBatch = theCustomAuthResources.map((keyData: any) => { + const { generateEncryptedPrivateKey, network } = keyData; + return { + ...generateEncryptedPrivateKey, + keyType: getKeyTypeFromNetwork(network), + }; + }); + + const { ids } = await storePrivateKeyBatch({ + sessionSig: firstSessionSig, + storedKeyMetadataBatch: keyParamsBatch, + litNetwork: params.litNodeClient.config.litNetwork, + }); + + const results = theCustomAuthResources.map( + (actionResult: any, ndx: any): BatchGeneratePrivateKeysActionResult => { + const { + generateEncryptedPrivateKey: { memo, publicKey }, + } = actionResult; + const id = ids[ndx]; // Result of writes is in same order as provided + + const signature = actionResult.signMessage?.signature; + + return { + ...(signature ? { signMessage: { signature } } : {}), + generateEncryptedPrivateKey: { + memo: memo, + id, + generatedPublicKey: publicKey, + pkpAddress, + }, + }; + } + ); + + return { pkpAddress, results }; +} diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts b/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts index 54363e47a2..fe86d60091 100644 --- a/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts +++ b/packages/wrapped-keys/src/lib/lit-actions-client/code-repository.ts @@ -89,6 +89,7 @@ function setLitActionsCode(repository: LitActionCodeRepositoryInput) { */ const litActionCodeRepositoryCommon: LitActionCodeRepositoryCommon = { batchGenerateEncryptedKeys: '', + triaAuthAndBatchGenerateEncryptedKeys: '', }; function assertIsLitActionKeyCommon( diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts b/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts index 83360f84fc..444eba609e 100644 --- a/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts +++ b/packages/wrapped-keys/src/lib/lit-actions-client/constants.ts @@ -21,6 +21,7 @@ const LIT_ACTION_CID_REPOSITORY: LitCidRepository = Object.freeze({ const LIT_ACTION_CID_REPOSITORY_COMMON: LitCidRepositoryCommon = Object.freeze({ batchGenerateEncryptedKeys: 'QmR8Zs7ctSEctxBrSnAYhMXFXCC1ub8K1xvMn5Js3NCSAA', + triaAuthAndBatchGenerateEncryptedKeys: 'xxx', }); export { LIT_ACTION_CID_REPOSITORY, LIT_ACTION_CID_REPOSITORY_COMMON }; diff --git a/packages/wrapped-keys/src/lib/lit-actions-client/types.ts b/packages/wrapped-keys/src/lib/lit-actions-client/types.ts index bda28ecd57..aec37a961b 100644 --- a/packages/wrapped-keys/src/lib/lit-actions-client/types.ts +++ b/packages/wrapped-keys/src/lib/lit-actions-client/types.ts @@ -6,7 +6,9 @@ export type LitActionType = | 'generateEncryptedKey' | 'exportPrivateKey'; -export type LitActionTypeCommon = 'batchGenerateEncryptedKeys'; +export type LitActionTypeCommon = + | 'batchGenerateEncryptedKeys' + | 'triaAuthAndBatchGenerateEncryptedKeys'; export type LitCidRepositoryEntry = Readonly>; diff --git a/yarn.lock b/yarn.lock index bd29e4cc9b..5a933819e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3594,6 +3594,11 @@ "@motionone/dom" "^10.16.4" tslib "^2.3.1" +"@multiformats/base-x@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" + integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== + "@multiformats/murmur3@^2.0.0": version "2.1.8" resolved "https://registry.yarnpkg.com/@multiformats/murmur3/-/murmur3-2.1.8.tgz#81c1c15b6391109f3febfca4b3205196615a04e9" @@ -9294,6 +9299,16 @@ cids@^0.7.1: multicodec "^1.0.0" multihashes "~0.4.15" +cids@^1.0.0, cids@^1.1.5, cids@^1.1.6: + version "1.1.9" + resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" + integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== + dependencies: + multibase "^4.0.1" + multicodec "^3.0.1" + multihashes "^4.0.1" + uint8arrays "^3.0.0" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -11401,7 +11416,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -err-code@^3.0.1: +err-code@^3.0.0, err-code@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920" integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== @@ -14078,6 +14093,14 @@ h3@^1.10.2, h3@^1.11.1: uncrypto "^0.1.3" unenv "^1.9.0" +hamt-sharding@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-2.0.1.tgz#f45686d0339e74b03b233bee1bde9587727129b6" + integrity sha512-vnjrmdXG9dDs1m/H4iJ6z0JFI2NtgsW5keRkTcM85NGak69Mkf5PHUqBz+Xs0T4sg0ppvj9O5EGAJo40FTxmmA== + dependencies: + sparse-array "^1.3.1" + uint8arrays "^3.0.0" + hamt-sharding@^3.0.0: version "3.0.6" resolved "https://registry.yarnpkg.com/hamt-sharding/-/hamt-sharding-3.0.6.tgz#3643107a3021af66ac95684aec87b196add5ba57" @@ -14843,6 +14866,15 @@ interface-blockstore@^4.0.0: interface-store "^3.0.0" multiformats "^11.0.0" +interface-ipld-format@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interface-ipld-format/-/interface-ipld-format-1.0.1.tgz#bee39c70c584a033e186ff057a2be89f215963e3" + integrity sha512-WV/ar+KQJVoQpqRDYdo7YPGYIUHJxCuOEhdvsRpzLqoOIVCqPKdMMYmsLL1nCRsF3yYNio+PAJbCKiv6drrEAg== + dependencies: + cids "^1.1.6" + multicodec "^3.0.1" + multihashes "^4.0.2" + interface-store@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-3.0.4.tgz#670d95ef45f3b7061d154c3cbfaf39a538167ad7" @@ -14903,6 +14935,14 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +ipfs-only-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ipfs-only-hash/-/ipfs-only-hash-4.0.0.tgz#b3bd60a244d9eb7394961aa9d812a2e5ac7c04d6" + integrity sha512-TE1DZCvfw8i3gcsTq3P4TFx3cKFJ3sluu/J3XINkJhIN9OwJgNMqKA+WnKx6ByCb1IoPXsTp1KM7tupElb6SyA== + dependencies: + ipfs-unixfs-importer "^7.0.1" + meow "^9.0.0" + ipfs-unixfs-importer@12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-12.0.1.tgz#316a52d8a793e9e006b1ee43edc50b83e00ef306" @@ -14924,6 +14964,34 @@ ipfs-unixfs-importer@12.0.1: uint8arraylist "^2.3.3" uint8arrays "^4.0.2" +ipfs-unixfs-importer@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs-importer/-/ipfs-unixfs-importer-7.0.3.tgz#b850e831ca9647d589ef50bc33421f65bab7bba6" + integrity sha512-qeFOlD3AQtGzr90sr5Tq1Bi8pT5Nr2tSI8z310m7R4JDYgZc6J1PEZO3XZQ8l1kuGoqlAppBZuOYmPEqaHcVQQ== + dependencies: + bl "^5.0.0" + cids "^1.1.5" + err-code "^3.0.1" + hamt-sharding "^2.0.0" + ipfs-unixfs "^4.0.3" + ipld-dag-pb "^0.22.2" + it-all "^1.0.5" + it-batch "^1.0.8" + it-first "^1.0.6" + it-parallel-batch "^1.0.9" + merge-options "^3.0.4" + multihashing-async "^2.1.0" + rabin-wasm "^0.1.4" + uint8arrays "^2.1.2" + +ipfs-unixfs@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-4.0.3.tgz#7c43e5726052ade4317245358ac541ef3d63d94e" + integrity sha512-hzJ3X4vlKT8FQ3Xc4M1szaFVjsc1ZydN+E4VQ91aXxfpjFn9G2wsMo1EFdAXNq/BUnN5dgqIOMP5zRYr3DTsAw== + dependencies: + err-code "^3.0.1" + protobufjs "^6.10.2" + ipfs-unixfs@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-9.0.1.tgz#d06e688e07ef4ce08d610337ba2fe8c143c386e7" @@ -14932,6 +15000,19 @@ ipfs-unixfs@^9.0.0: err-code "^3.0.1" protobufjs "^7.0.0" +ipld-dag-pb@^0.22.2: + version "0.22.3" + resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.22.3.tgz#6d5af28b5752236a5cb0e0a1888c87dd733b55cd" + integrity sha512-dfG5C5OVAR4FEP7Al2CrHWvAyIM7UhAQrjnOYOIxXGQz5NlEj6wGX0XQf6Ru6or1na6upvV3NQfstapQG8X2rg== + dependencies: + cids "^1.0.0" + interface-ipld-format "^1.0.0" + multicodec "^3.0.1" + multihashing-async "^2.0.0" + protobufjs "^6.10.2" + stable "^0.1.8" + uint8arrays "^2.0.5" + iron-webcrypto@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz#aa60ff2aa10550630f4c0b11fd2442becdb35a6f" @@ -15632,21 +15713,43 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +it-all@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335" + integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A== + it-all@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-all/-/it-all-2.0.1.tgz#45d530ecf6e13fb81d7ba583cdfd55ffdb376b05" integrity sha512-9UuJcCRZsboz+HBQTNOau80Dw+ryGaHYFP/cPYzFBJBFcfDathMYnhHk4t52en9+fcyDGPTdLB+lFc1wzQIroA== +it-batch@^1.0.8, it-batch@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-1.0.9.tgz#7e95aaacb3f9b1b8ca6c8b8367892171d6a5b37f" + integrity sha512-7Q7HXewMhNFltTsAMdSz6luNhyhkhEtGGbYek/8Xb/GiqYMtwUmopE1ocPSiJKKp3rM4Dt045sNFoUu+KZGNyA== + it-batch@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-batch/-/it-batch-2.0.1.tgz#a0822be9b18743c41d8525835f788a7f297ba41f" integrity sha512-2gWFuPzamh9Dh3pW+OKjc7UwJ41W4Eu2AinVAfXDMfrC5gXfm3b1TF+1UzsygBUgKBugnxnGP+/fFRyn+9y1mQ== +it-first@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/it-first/-/it-first-1.0.7.tgz#a4bef40da8be21667f7d23e44dae652f5ccd7ab1" + integrity sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g== + it-first@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-first/-/it-first-2.0.1.tgz#75d66b254c385ae3a1906def060a69006a437cef" integrity sha512-noC1oEQcWZZMUwq7VWxHNLML43dM+5bviZpfmkxkXlvBe60z7AFRqpZSga9uQBo792jKv9otnn1IjA4zwgNARw== +it-parallel-batch@^1.0.9: + version "1.0.11" + resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-1.0.11.tgz#f889b4e1c7a62ef24111dbafbaaa010b33d00f69" + integrity sha512-UWsWHv/kqBpMRmyZJzlmZeoAMA0F3SZr08FBdbhtbe+MtoEBgr/ZUAKrnenhXCBrsopy76QjRH2K/V8kNdupbQ== + dependencies: + it-batch "^1.0.9" + it-parallel-batch@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/it-parallel-batch/-/it-parallel-batch-2.0.1.tgz#23eb07bbeb73521253d7c8a1566b53137103077c" @@ -17781,6 +17884,24 @@ meow@^8.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -18264,6 +18385,13 @@ multibase@^0.7.0: base-x "^3.0.8" buffer "^5.5.0" +multibase@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" + integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== + dependencies: + "@multiformats/base-x" "^4.0.1" + multibase@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" @@ -18287,6 +18415,14 @@ multicodec@^1.0.0: buffer "^5.6.0" varint "^5.0.0" +multicodec@^3.0.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" + integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== + dependencies: + uint8arrays "^3.0.0" + varint "^6.0.0" + multiformats@^11.0.0, multiformats@^11.0.2: version "11.0.2" resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-11.0.2.tgz#b14735efc42cd8581e73895e66bebb9752151b60" @@ -18316,6 +18452,27 @@ multihashes@^0.4.15, multihashes@~0.4.15: multibase "^0.7.0" varint "^5.0.0" +multihashes@^4.0.1, multihashes@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" + integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== + dependencies: + multibase "^4.0.1" + uint8arrays "^3.0.0" + varint "^5.0.2" + +multihashing-async@^2.0.0, multihashing-async@^2.1.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843" + integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg== + dependencies: + blakejs "^1.1.0" + err-code "^3.0.0" + js-sha3 "^0.8.0" + multihashes "^4.0.1" + murmurhash3js-revisited "^3.0.0" + uint8arrays "^3.0.0" + multimatch@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-5.0.0.tgz#932b800963cea7a31a033328fa1e0c3a1874dbe6" @@ -20324,7 +20481,7 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== -protobufjs@^6.8.8, protobufjs@~6.11.2, protobufjs@~6.11.3: +protobufjs@^6.10.2, protobufjs@^6.8.8, protobufjs@~6.11.2, protobufjs@~6.11.3: version "6.11.4" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== @@ -22245,6 +22402,11 @@ ssri@^9.0.0, ssri@^9.0.1: dependencies: minipass "^3.1.1" +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -23489,6 +23651,13 @@ typescript@~5.3.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +typestub-ipfs-only-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typestub-ipfs-only-hash/-/typestub-ipfs-only-hash-4.0.0.tgz#12e7d0e13947884b5b7d8091b9a17073fdf71d2d" + integrity sha512-HKLePX0XiPiyqoueSfvCLL9SIzvKBXjASaRoR0yk/gUbbK7cqejU6/tjhihwmzBCvWbx5aMQ2LYsYIpMK7Ikpg== + dependencies: + ipfs-only-hash "^4.0.0" + u2f-api@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" @@ -23518,6 +23687,13 @@ uint8arrays@3.1.0: dependencies: multiformats "^9.4.2" +uint8arrays@^2.0.5, uint8arrays@^2.1.2: + version "2.1.10" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" + integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== + dependencies: + multiformats "^9.4.2" + uint8arrays@^3.0.0, uint8arrays@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" @@ -24031,11 +24207,16 @@ valtio@1.11.0: proxy-compare "2.5.1" use-sync-external-store "1.2.0" -varint@^5.0.0: +varint@^5.0.0, varint@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== +varint@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" + integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== + varuint-bitcoin@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92"