diff --git a/packages/e2e/src/tickets/jss100-custom-contract-accs.spec.ts b/packages/e2e/src/tickets/jss100-custom-contract-accs.spec.ts new file mode 100644 index 000000000..d59dde5a5 --- /dev/null +++ b/packages/e2e/src/tickets/jss100-custom-contract-accs.spec.ts @@ -0,0 +1,144 @@ +import { createAuthManager, storagePlugins } from '@lit-protocol/auth'; +import { createLitClient } from '@lit-protocol/lit-client'; +import { nagaDev } from '@lit-protocol/networks'; +import { privateKeyToAccount } from 'viem/accounts'; +import { + createAccBuilder, + UnifiedAccessControlCondition, +} from '@lit-protocol/access-control-conditions'; + +import { createPublicClient, http } from 'viem'; +import { baseSepolia } from 'viem/chains'; + +const liveMasterAccount = privateKeyToAccount( + process.env['LIVE_MASTER_ACCOUNT'] as `0x${string}` +); + +const rawAccs = [ + { + conditionType: 'evmContract', + contractAddress: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', + functionName: 'balanceOf', + functionParams: [':userAddress'], + functionAbi: { + inputs: [{ internalType: 'address', name: 'account', type: 'address' }], + name: 'balanceOf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + chain: 'baseSepolia', + returnValueTest: { + key: '', + comparator: '>=', + value: '0', + }, + }, +] as UnifiedAccessControlCondition; + +describe('jss100 custom contract accs', () => { + beforeAll(async () => { + const client = createPublicClient({ + chain: baseSepolia, + transport: http(), + }); + + const balance = await client.readContract({ + address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', + abi: [ + { + constant: true, + inputs: [{ name: 'account', type: 'address' }], + name: 'balanceOf', + outputs: [{ name: '', type: 'uint256' }], + payable: false, + stateMutability: 'view', + type: 'function', + }, + ], + functionName: 'balanceOf', + args: [liveMasterAccount.address], + }); + + if (BigInt(balance) <= 0n) { + throw new Error( + `Test account ${liveMasterAccount.address} has no balance for token 0x036CbD53842c5426634e7929541eC2318f3dCF7e. Please get some before running the test.` + ); + } + }); + + it('should be able to use the custom contract accs api - evmContract conditions', async () => { + console.log( + '🔧 [TEST] Testing evmContract conditions (rawAccs):', + JSON.stringify(rawAccs, null, 2) + ); + + console.log( + 'Setting up permissions for address:', + liveMasterAccount.address + ); + + console.log('🔧 [SESSION] Creating fresh litClient and clearing storage'); + + const litClient = await createLitClient({ network: nagaDev }); + + // Use unique storage path with timestamp to prevent session reuse + const uniqueStoragePath = `.e2e/jss100-${Date.now()}`; + console.log('🔧 [SESSION] Using unique storage path:', uniqueStoragePath); + + const authManager = createAuthManager({ + storage: storagePlugins.localStorageNode({ + appName: 'jss100-custom-contract-accs', + networkName: 'naga-dev', + storagePath: uniqueStoragePath, + }), + }); + + /** + * ==================================== + * Create the auth context + * ==================================== + */ + const aliceEoaAuthContext = await authManager.createEoaAuthContext({ + config: { + account: liveMasterAccount, + }, + authConfig: { + statement: 'I authorize the Lit Protocol to execute this Lit Action.', + domain: 'example.com', + resources: [ + ['lit-action-execution', '*'], + ['pkp-signing', '*'], + ['access-control-condition-decryption', '*'], + ], + capabilityAuthSigs: [], + expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(), + }, + litClient: litClient, + }); + + // Handle both array and single condition formats correctly + const unifiedAccs = createAccBuilder().unifiedAccs(rawAccs).build(); + + console.log('unifiedAccs:', JSON.stringify(unifiedAccs, null, 2)); + + const stringData = 'Hello world'; + const encryptedStringData = await litClient.encrypt({ + dataToEncrypt: stringData, + unifiedAccessControlConditions: unifiedAccs, + }); + + console.log(encryptedStringData); + + // Use the same account to decrypt the data + const decryptedStringData = await litClient.decrypt({ + data: encryptedStringData, + unifiedAccessControlConditions: unifiedAccs, + authContext: aliceEoaAuthContext, + }); + + console.log('decryptedStringData:', decryptedStringData); + + expect(decryptedStringData.convertedData).toBe(stringData); + }); +}); diff --git a/packages/lit-client/src/lib/LitClient/createLitClient.ts b/packages/lit-client/src/lib/LitClient/createLitClient.ts index 618759aef..faf5721fc 100644 --- a/packages/lit-client/src/lib/LitClient/createLitClient.ts +++ b/packages/lit-client/src/lib/LitClient/createLitClient.ts @@ -17,6 +17,7 @@ import type { import { AuthContextSchema2, AuthData, + ChainSchema, EncryptedVersion1Schema, HexPrefixedSchema, JsonSignCustomSessionKeyRequestForPkpReturnSchema, @@ -663,7 +664,7 @@ export const _createNagaLitClient = async ( unifiedAccessControlConditions: params.unifiedAccessControlConditions, connectionInfo: currentConnectionInfo, version: networkModule.version, - chain: params.chain, + chain: ChainSchema.parse(params.chain), jitContext, })) as RequestItem>[]; diff --git a/packages/networks/src/networks/vNaga/shared/managers/api-manager/decrypt/decrypt.RequestDataSchema.ts b/packages/networks/src/networks/vNaga/shared/managers/api-manager/decrypt/decrypt.RequestDataSchema.ts index 2523102a9..1c0421544 100644 --- a/packages/networks/src/networks/vNaga/shared/managers/api-manager/decrypt/decrypt.RequestDataSchema.ts +++ b/packages/networks/src/networks/vNaga/shared/managers/api-manager/decrypt/decrypt.RequestDataSchema.ts @@ -1,6 +1,8 @@ import { z } from 'zod'; import { MultipleAccessControlConditionsSchema } from '@lit-protocol/access-control-conditions-schemas'; import { AuthSigSchema } from '@lit-protocol/schemas'; +import { FormattedMultipleAccs } from '@lit-protocol/types'; +import { getFormattedAccessControlConditions } from '@lit-protocol/access-control-conditions'; export const DecryptRequestDataSchema = MultipleAccessControlConditionsSchema.extend({ @@ -8,4 +10,19 @@ export const DecryptRequestDataSchema = dataToEncryptHash: z.string(), authSig: AuthSigSchema, chain: z.string(), + }).transform((data) => { + const { + formattedAccessControlConditions, + formattedEVMContractConditions, + formattedSolRpcConditions, + formattedUnifiedAccessControlConditions, + }: FormattedMultipleAccs = getFormattedAccessControlConditions(data); + + return { + ...data, + accessControlConditions: formattedAccessControlConditions, + evmContractConditions: formattedEVMContractConditions, + solRpcConditions: formattedSolRpcConditions, + unifiedAccessControlConditions: formattedUnifiedAccessControlConditions, + }; }); diff --git a/packages/networks/src/storage/types.ts b/packages/networks/src/storage/types.ts index 8b148e09f..634b0f077 100644 --- a/packages/networks/src/storage/types.ts +++ b/packages/networks/src/storage/types.ts @@ -1,4 +1,4 @@ -import { PKPInfo } from '@lit-protocol/types'; +import { PKPData } from '@lit-protocol/schemas'; export interface PKPStorageProvider { readPKPTokens?(params: { @@ -37,11 +37,11 @@ export interface PKPStorageProvider { readPKPs?(params: { authMethodType: number | bigint; authMethodId: string; - }): Promise; + }): Promise; writePKPs?(params: { authMethodType: number | bigint; authMethodId: string; - pkps: PKPInfo[]; + pkps: PKPData[]; }): Promise; } diff --git a/packages/schemas/src/lib/schemas.ts b/packages/schemas/src/lib/schemas.ts index 81bbcbc23..d8455e653 100644 --- a/packages/schemas/src/lib/schemas.ts +++ b/packages/schemas/src/lib/schemas.ts @@ -218,14 +218,14 @@ export const JsonSchema: z.ZodType = z.lazy(() => ); export const HexSchema = z.string().regex(/^0x[0-9a-fA-F]+$/); -export const ChainSchema = z.string(); +export const ChainSchema = z.string().default('ethereum'); export const EvmChainSchema = z.enum(LIT_CHAINS_KEYS); export const ChainedSchema = z.object({ /** * The chain name of the chain that will be used. See LIT_CHAINS for currently supported chains. */ - chain: ChainSchema, + chain: ChainSchema.optional(), }); export const PricedSchema = z.object({