Skip to content

Commit b09d690

Browse files
committed
feat: only create new app version if abilities differ. only permit app if not permitted
1 parent 316784c commit b09d690

File tree

5 files changed

+76
-19
lines changed

5 files changed

+76
-19
lines changed

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: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,78 @@ 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
1114
* @param abilityPolicies - Array of policy IPFS CIDs for each ability
15+
* @param registerNewVersionOverride - Whether to register a new version even if the latest version already has the same abilities and policies
1216
*/
1317
export async function registerNewAppVersion({
1418
abilityIpfsCids,
1519
abilityPolicies,
20+
registerNewVersionOverride = false,
1621
}: {
1722
abilityIpfsCids: string[];
1823
abilityPolicies: string[][];
24+
registerNewVersionOverride?: boolean;
1925
}) {
2026
const app = await getAppInfo();
2127

2228
if (!app) {
2329
throw new Error('App was expected, but not found. Please register a new app first.');
2430
}
2531

26-
const { appId } = app;
32+
const { appId, appVersion: latestVersion } = app;
2733

2834
const {
2935
wallets: { appManager },
3036
} = await getChainHelpers();
3137

32-
const { txHash, newAppVersion } = await getClient({
33-
signer: appManager,
34-
}).registerNextVersion({
38+
const client = getClient({ signer: appManager });
39+
40+
if (!registerNewVersionOverride) {
41+
// Get the existing app version to compare
42+
const existingAppVersion = await client.getAppVersion({
43+
appId,
44+
version: latestVersion,
45+
});
46+
47+
if (existingAppVersion) {
48+
// Extract existing abilities and policies
49+
const existingAbilityIpfsCids = existingAppVersion.appVersion.abilities.map(
50+
(ability) => ability.abilityIpfsCid,
51+
);
52+
const existingAbilityPolicies = existingAppVersion.appVersion.abilities.map(
53+
(ability) => ability.policyIpfsCids,
54+
);
55+
56+
// Compare arrays (order matters for abilities and policies)
57+
const abilitiesMatch =
58+
existingAbilityIpfsCids.length === abilityIpfsCids.length &&
59+
existingAbilityIpfsCids.every((cid, index) => cid === abilityIpfsCids[index]);
60+
61+
const policiesMatch =
62+
existingAbilityPolicies.length === abilityPolicies.length &&
63+
existingAbilityPolicies.every((policies, index) => {
64+
const newPolicies = abilityPolicies[index];
65+
return (
66+
policies.length === newPolicies.length &&
67+
policies.every((policy, policyIndex) => policy === newPolicies[policyIndex])
68+
);
69+
});
70+
71+
if (abilitiesMatch && policiesMatch) {
72+
console.log(
73+
`App version ${latestVersion} already has the same abilities and policies. Skipping registration.`,
74+
);
75+
return { appId, appVersion: latestVersion };
76+
}
77+
}
78+
}
79+
80+
// Register new version if abilities or policies have changed
81+
const { txHash, newAppVersion } = await client.registerNextVersion({
3582
appId,
3683
versionAbilities: {
3784
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)