Skip to content

Commit 17104ec

Browse files
Merge pull request #395 from LIT-Protocol/feat/e2e-utils-enhancements
Feat: E2E test utils enhancements
2 parents 316784c + 21652bb commit 17104ec

File tree

6 files changed

+97
-20
lines changed

6 files changed

+97
-20
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
e2e-test-utils: minor
3+
---
4+
5+
Add logic to registerNewAppVersion to avoid registering a new App version if the given Ability and Policy config matches the latest App version. Add logic to permitAppVersionForAgentWalletPkp to avoid permitting the App version if it's already been permitted.

packages/apps/ability-aerodrome-swap/jest.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ module.exports = {
66
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
77
transformIgnorePatterns: [
88
// PNPM style: scoped packages with `.` become `+`, and non-scoped stay the same
9-
// Include all @account-kit, @aa-sdk, @wagmi packages and sugar-sdk using wildcards
10-
'<rootDir>/node_modules/.pnpm/(?!(@noble\\+secp256k1|cbor2|@cto\\.af\\+wtf8|@t3-oss\\+env-core|@account-kit\\+[^@]+|@aa-sdk\\+[^@]+|@lit-protocol\\+vincent-scaffold-sdk|@wagmi\\+[^@]+|@tanstack\\+[^@]+|sugar-sdk)@)',
9+
// Include all @account-kit, @aa-sdk, @wagmi packages and @dromos-labs/sdk.js using wildcards
10+
'<rootDir>/node_modules/.pnpm/(?!(@noble\\+secp256k1|cbor2|@cto\\.af\\+wtf8|@t3-oss\\+env-core|@account-kit\\+[^@]+|@aa-sdk\\+[^@]+|@lit-protocol\\+vincent-scaffold-sdk|@wagmi\\+[^@]+|@tanstack\\+[^@]+|@dromos-labs\\+sdk\\.js)@)',
1111

1212
// Absolute path variant (in case of different module resolution by Jest)
13-
`${path.join(__dirname, '../..')}/node_modules/.pnpm/(?!(@noble\\+secp256k1|cbor2|@cto\\.af\\+wtf8|@t3-oss\\+env-core|@account-kit\\+[^@]+|@aa-sdk\\+[^@]+|@lit-protocol\\+vincent-scaffold-sdk|@wagmi\\+[^@]+|@tanstack\\+[^@]+|sugar-sdk)@)`,
13+
`${path.join(__dirname, '../..')}/node_modules/.pnpm/(?!(@noble\\+secp256k1|cbor2|@cto\\.af\\+wtf8|@t3-oss\\+env-core|@account-kit\\+[^@]+|@aa-sdk\\+[^@]+|@lit-protocol\\+vincent-scaffold-sdk|@wagmi\\+[^@]+|@tanstack\\+[^@]+|@dromos-labs\\+sdk\\.js)@)`,
1414

1515
// Fallback for non-PNPM node_modules structure
16-
'node_modules/(?!.pnpm|@noble/secp256k1|cbor2|@cto\\.af/wtf8|@t3-oss/env-core|@account-kit/[^/]+|@aa-sdk/[^/]+|@lit-protocol/vincent-scaffold-sdk|@wagmi/[^/]+|@tanstack/[^/]+|sugar-sdk)',
16+
'node_modules/(?!.pnpm|@noble/secp256k1|cbor2|@cto\\.af/wtf8|@t3-oss/env-core|@account-kit/[^/]+|@aa-sdk/[^/]+|@lit-protocol/vincent-scaffold-sdk|@wagmi/[^/]+|@tanstack/[^/]+|@dromos-labs/sdk.js)',
1717
],
1818
};

packages/apps/ability-aerodrome-swap/test/e2e/swap-no-sponsorship.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ describe('Aerodrome Swap Ability E2E Tests without Gas Sponsorship', () => {
7878
appId = newApp.appId;
7979
appVersion = newApp.appVersion;
8080
} else {
81-
// TODO Future optimization: Only create a new app version if the existing app version doesn't have the same ability and policy IPFS CIDs
8281
console.log('[beforeAll] Existing app, registering new app version');
8382
const newAppVersion = await appManager.registerNewAppVersion({
8483
abilityIpfsCids,

packages/apps/ability-aerodrome-swap/test/e2e/swap-with-sponsorship.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ describe('Aerodrome Swap Ability E2E Tests with Alchemy Gas Sponsorship', () =>
8484
appId = newApp.appId;
8585
appVersion = newApp.appVersion;
8686
} else {
87-
// TODO Future optimization: Only create a new app version if the existing app version doesn't have the same ability and policy IPFS CIDs
8887
const newAppVersion = await appManager.registerNewAppVersion({
8988
abilityIpfsCids,
9089
abilityPolicies,

packages/libs/e2e-test-utils/src/lib/appManager/register-new-app-version.ts

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,93 @@ import { getAppInfo } from '../delegatee/get-app-info';
77
* Registers a new app version. On-chain app versions are immutable, so any time you modify
88
* abilities or policies, you must register a new version of your app using the new ipfs CIDs
99
*
10+
* This function will check if the latest app version already has the same abilities and policies.
11+
* If they match, it will return the existing appVersion without registering a new one.
12+
*
1013
* @param abilityIpfsCids - Array of ability IPFS CIDs to register
11-
* @param abilityPolicies - Array of policy IPFS CIDs for each ability
14+
* @param abilityPolicies - Array of policy IPFS CIDs for each ability (must be parallel to abilityIpfsCids)
15+
* @param registerNewVersionOverride - Whether to register a new version even if the latest version already has the same abilities and policies
16+
*
17+
* @remarks
18+
* Assumptions:
19+
* - `abilityIpfsCids` and `abilityPolicies` are parallel arrays where `abilityPolicies[i]` contains
20+
* the policy CIDs for the ability at `abilityIpfsCids[i]`
21+
* - The comparison is order-independent for both abilities and policies within each ability
22+
* - Two app versions are considered equivalent if they have the same set of abilities (regardless of order)
23+
* and each ability has the same set of policies (regardless of order)
1224
*/
1325
export async function registerNewAppVersion({
1426
abilityIpfsCids,
1527
abilityPolicies,
28+
registerNewVersionOverride = false,
1629
}: {
1730
abilityIpfsCids: string[];
1831
abilityPolicies: string[][];
32+
registerNewVersionOverride?: boolean;
1933
}) {
2034
const app = await getAppInfo();
2135

2236
if (!app) {
2337
throw new Error('App was expected, but not found. Please register a new app first.');
2438
}
2539

26-
const { appId } = app;
40+
const { appId, appVersion: latestVersion } = app;
2741

2842
const {
2943
wallets: { appManager },
3044
} = await getChainHelpers();
3145

32-
const { txHash, newAppVersion } = await getClient({
33-
signer: appManager,
34-
}).registerNextVersion({
46+
const client = getClient({ signer: appManager });
47+
48+
if (!registerNewVersionOverride) {
49+
// Get the existing app version to compare
50+
const existingAppVersion = await client.getAppVersion({
51+
appId,
52+
version: latestVersion,
53+
});
54+
55+
if (existingAppVersion) {
56+
// Create a map from ability CID to its policies for easy lookup
57+
const existingAbilityMap = new Map<string, string[]>();
58+
existingAppVersion.appVersion.abilities.forEach((ability) => {
59+
existingAbilityMap.set(ability.abilityIpfsCid, ability.policyIpfsCids);
60+
});
61+
62+
// Check if we have the same number of abilities and compare them
63+
if (existingAbilityMap.size === abilityIpfsCids.length) {
64+
// For each ability in the new version, check if it exists with the same policies
65+
const allMatch = abilityIpfsCids.every((abilityId, index) => {
66+
const existingPolicies = existingAbilityMap.get(abilityId);
67+
if (existingPolicies === undefined) return false; // Ability doesn't exist in current version
68+
69+
const newPolicies = abilityPolicies[index];
70+
if (newPolicies === undefined) {
71+
throw new Error(
72+
`Parallel arrays are not in sync: abilityPolicies[${index}] is undefined for ability '${abilityId}'.`,
73+
);
74+
}
75+
76+
// Compare policy arrays (order-independent)
77+
if (existingPolicies.length !== newPolicies.length) return false;
78+
79+
const sortedExisting = [...existingPolicies].sort();
80+
const sortedNew = [...newPolicies].sort();
81+
82+
return sortedExisting.every((policy, i) => policy === sortedNew[i]);
83+
});
84+
85+
if (allMatch) {
86+
console.log(
87+
`App version ${latestVersion} already has the same abilities and policies. Skipping registration.`,
88+
);
89+
return { appId, appVersion: latestVersion };
90+
}
91+
}
92+
}
93+
}
94+
95+
// Register new version if abilities or policies have changed
96+
const { txHash, newAppVersion } = await client.registerNextVersion({
3597
appId,
3698
versionAbilities: {
3799
abilityIpfsCids: abilityIpfsCids,

packages/libs/e2e-test-utils/src/lib/delegator/permit-vincent-app-version.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import type { PkpInfo } from '../mint-new-pkp';
77
import { getChainHelpers } from '../chain';
88

99
/**
10-
* Adds Vincent delegation permission for a specific app version for the user's Agent Wallet PKP
10+
* Adds Vincent delegation permission for a specific app version for the user's Agent Wallet PKP.
11+
*
12+
* This function will check if the requested app version is already permitted. If it is,
13+
* it will skip the permission step and return early. If a different version is permitted,
14+
* it will remove the old permission before adding the new one.
1115
*/
1216
export async function permitAppVersionForAgentWalletPkp({
1317
permissionData,
@@ -24,27 +28,35 @@ export async function permitAppVersionForAgentWalletPkp({
2428
wallets: { agentWalletOwner },
2529
} = await getChainHelpers();
2630

27-
const existingPermittedAppVersion = await getClient({
31+
const client = getClient({
2832
signer: agentWalletOwner,
29-
}).getPermittedAppVersionForPkp({
33+
});
34+
35+
const existingPermittedAppVersion = await client.getPermittedAppVersionForPkp({
3036
pkpEthAddress: agentPkpInfo.ethAddress,
3137
appId,
3238
});
3339

40+
// Check if the requested version is already permitted
41+
if (existingPermittedAppVersion === appVersion) {
42+
console.log(
43+
`App version ${appVersion} is already permitted for Agent Wallet PKP ${agentPkpInfo.ethAddress}. Skipping permission.`,
44+
);
45+
return;
46+
}
47+
48+
// If a different version is permitted, remove it first
3449
if (existingPermittedAppVersion) {
3550
console.log(`Removing existing permission for app version ${existingPermittedAppVersion}`);
36-
await getClient({
37-
signer: agentWalletOwner,
38-
}).unPermitApp({
51+
await client.unPermitApp({
3952
pkpEthAddress: agentPkpInfo.ethAddress,
4053
appId,
4154
appVersion: existingPermittedAppVersion,
4255
});
4356
}
4457

45-
const result = await getClient({
46-
signer: agentWalletOwner,
47-
}).permitApp({
58+
// Permit the new version
59+
const result = await client.permitApp({
4860
pkpEthAddress: agentPkpInfo.ethAddress,
4961
appId,
5062
appVersion,

0 commit comments

Comments
 (0)