Skip to content

Commit fa5b003

Browse files
committed
refactor(passport)!: BSB-6: remove StarkEx support from Passport SDK
Remove all StarkEx/IMX provider code from the Passport SDK package. This is a breaking change - connectImx() and connectImxSilent() public methods are removed, and PassportOverrides no longer accepts IMX-specific fields (imxPublicApiDomain, immutableXClient, imxApiClients). Deleted: starkEx/ directory (provider, factory, guardian client, workflows), utils/imxUser.ts, and all associated tests. Simplified linkExternalWallet() to use isUserZkEvm() instead of toUserImx().
1 parent 0904781 commit fa5b003

21 files changed

Lines changed: 8 additions & 1688 deletions

packages/passport/sdk/src/Passport.test.ts

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ jest.mock('@imtbl/wallet', () => {
3939
return {
4040
connectWallet: connectWalletMock,
4141
ZkEvmProvider: jest.fn(),
42-
GuardianClient: jest.fn(),
43-
MagicTEESigner: jest.fn(),
44-
WalletConfiguration: jest.fn(),
45-
ConfirmationScreen: jest.fn(),
4642
__mocked: {
4743
connectWalletMock,
4844
},
@@ -68,12 +64,6 @@ jest.mock('@imtbl/generated-clients', () => {
6864
return {
6965
...actual,
7066
MultiRollupApiClients: multiRollupApiClientsFactory,
71-
MagicTeeApiClients: jest.fn(),
72-
createConfig: jest.fn((config) => config),
73-
imxApiConfig: {
74-
getSandbox: jest.fn(() => ({ basePath: 'sandbox' })),
75-
getProduction: jest.fn(() => ({ basePath: 'production' })),
76-
},
7767
};
7868
});
7969

@@ -97,28 +87,6 @@ jest.mock('@imtbl/metrics', () => {
9787
};
9888
});
9989

100-
jest.mock('./starkEx', () => {
101-
const factoryMock = {
102-
getProvider: jest.fn(),
103-
getProviderSilent: jest.fn(),
104-
};
105-
const passportImxProviderFactory = jest.fn().mockImplementation(() => factoryMock);
106-
return {
107-
PassportImxProviderFactory: passportImxProviderFactory,
108-
};
109-
});
110-
111-
jest.mock('./starkEx/imxGuardianClient', () => ({
112-
ImxGuardianClient: jest.fn().mockImplementation(() => ({
113-
evaluateTransaction: jest.fn(),
114-
})),
115-
}));
116-
117-
jest.mock('./utils/imxUser', () => ({
118-
toUserImx: jest.fn().mockReturnValue({}),
119-
}));
120-
121-
const { PassportImxProviderFactory: passportImxProviderFactoryMock } = jest.requireMock('./starkEx');
12290
const { __mocked: metricsMocks } = jest.requireMock('@imtbl/metrics');
12391
const { __mocked: walletMocks } = jest.requireMock('@imtbl/wallet');
12492
const { trackErrorMock } = metricsMocks;
@@ -144,51 +112,13 @@ describe('Passport', () => {
144112

145113
const getLatestAuthInstance = () => mockAuthInstances[mockAuthInstances.length - 1];
146114
const getLatestMultiRollupInstance = () => multiRollupInstances[multiRollupInstances.length - 1];
147-
const getFactoryInstance = () => (passportImxProviderFactoryMock as jest.Mock).mock.results.slice(-1)[0]?.value;
148115

149116
beforeEach(() => {
150117
jest.clearAllMocks();
151118
mockAuthInstances.length = 0;
152119
multiRollupInstances.length = 0;
153120
});
154121

155-
describe('connectImx', () => {
156-
it('returns provider from factory', async () => {
157-
const passport = createPassport();
158-
const factory = getFactoryInstance();
159-
const provider = { kind: 'imx' };
160-
factory.getProvider.mockResolvedValue(provider);
161-
162-
const result = await passport.connectImx();
163-
164-
expect(result).toBe(provider);
165-
expect(factory.getProvider).toHaveBeenCalledTimes(1);
166-
});
167-
168-
it('tracks error when factory throws', async () => {
169-
const passport = createPassport();
170-
const factory = getFactoryInstance();
171-
const error = new Error('boom');
172-
factory.getProvider.mockRejectedValue(error);
173-
174-
await expect(passport.connectImx()).rejects.toThrow(error);
175-
expect(trackErrorMock).toHaveBeenCalledWith('passport', 'connectImx', error, { flowId: 'flow-id' });
176-
});
177-
});
178-
179-
describe('connectImxSilent', () => {
180-
it('returns null when factory resolves null', async () => {
181-
const passport = createPassport();
182-
const factory = getFactoryInstance();
183-
factory.getProviderSilent.mockResolvedValue(null);
184-
185-
const result = await passport.connectImxSilent();
186-
187-
expect(result).toBeNull();
188-
expect(factory.getProviderSilent).toHaveBeenCalledTimes(1);
189-
});
190-
});
191-
192122
describe('connectEvm', () => {
193123
it('returns provider from connectWallet', async () => {
194124
const provider = { kind: 'zkEvm' };

packages/passport/sdk/src/Passport.ts

Lines changed: 7 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { IMXProvider } from '@imtbl/x-provider';
21
import {
3-
createConfig, ImxApiClients, imxApiConfig, MagicTeeApiClients, MultiRollupApiClients,
2+
MultiRollupApiClients,
43
} from '@imtbl/generated-clients';
5-
import { IMXClient } from '@imtbl/x-client';
64
import { Environment } from '@imtbl/config';
75

86
import { setPassportClientId, trackError, trackFlow } from '@imtbl/metrics';
@@ -16,47 +14,21 @@ import type { DirectLoginOptions } from '@imtbl/auth';
1614
import {
1715
connectWallet,
1816
ZkEvmProvider,
19-
WalletConfiguration,
20-
GuardianClient,
21-
MagicTEESigner,
2217
ChainConfig,
23-
ConfirmationScreen,
2418
} from '@imtbl/wallet';
2519
import type { LinkWalletParams, LinkedWallet } from '@imtbl/wallet';
2620
import {
2721
PassportModuleConfiguration,
2822
ConnectEvmArguments,
2923
LoginArguments,
3024
} from './types';
31-
import { toUserImx } from './utils/imxUser';
32-
import { PassportImxProviderFactory } from './starkEx';
3325
import { PassportConfiguration } from './config';
3426
import { withMetricsAsync } from './utils/metrics';
3527
import { PassportError, PassportErrorType } from './errors/passportError';
36-
import { ImxGuardianClient } from './starkEx/imxGuardianClient';
3728
import { getHttpErrorResponse } from './utils/httpError';
3829

39-
const buildImxClientConfig = (passportModuleConfiguration: PassportModuleConfiguration) => {
40-
if (passportModuleConfiguration.overrides) {
41-
return createConfig({ basePath: passportModuleConfiguration.overrides.imxPublicApiDomain });
42-
}
43-
if (passportModuleConfiguration.baseConfig.environment === Environment.SANDBOX) {
44-
return imxApiConfig.getSandbox();
45-
}
46-
return imxApiConfig.getProduction();
47-
};
48-
49-
const buildImxApiClients = (passportModuleConfiguration: PassportModuleConfiguration) => {
50-
if (passportModuleConfiguration.overrides?.imxApiClients) return passportModuleConfiguration.overrides.imxApiClients;
51-
52-
const config = buildImxClientConfig(passportModuleConfiguration);
53-
return new ImxApiClients(config);
54-
};
55-
5630
export const buildPrivateVars = (passportModuleConfiguration: PassportModuleConfiguration) => {
5731
const passportConfig = new PassportConfiguration(passportModuleConfiguration);
58-
// Create auth configuration for confirmation screen
59-
// Create Auth instance (public API)
6032
const auth = new Auth({
6133
...passportModuleConfiguration,
6234
authenticationDomain: passportConfig.authenticationDomain,
@@ -65,75 +37,10 @@ export const buildPrivateVars = (passportModuleConfiguration: PassportModuleConf
6537
passportDomain: passportConfig.passportDomain,
6638
});
6739

68-
const authConfig = auth.getConfig();
69-
const confirmationScreen = new ConfirmationScreen(authConfig);
70-
71-
// Create wallet configuration with concrete URLs (no environment)
72-
// PassportConfiguration translates environment → URLs
73-
const walletConfig = new WalletConfiguration({
74-
passportDomain: passportConfig.passportDomain,
75-
zkEvmRpcUrl: passportConfig.zkEvmRpcUrl,
76-
relayerUrl: passportConfig.relayerUrl,
77-
indexerMrBasePath: passportConfig.multiRollupConfig.indexer.basePath || passportConfig.passportDomain,
78-
jsonRpcReferrer: passportModuleConfiguration.jsonRpcReferrer,
79-
forceScwDeployBeforeMessageSignature: passportModuleConfiguration.forceScwDeployBeforeMessageSignature,
80-
crossSdkBridgeEnabled: passportModuleConfiguration.crossSdkBridgeEnabled,
81-
});
82-
83-
// Setup IMX-specific components
84-
const multiRollupApiClients = new MultiRollupApiClients(passportConfig.multiRollupConfig);
85-
86-
const immutableXClient = passportModuleConfiguration.overrides
87-
? passportModuleConfiguration.overrides.immutableXClient
88-
: new IMXClient({ baseConfig: passportModuleConfiguration.baseConfig });
89-
90-
// Create Guardian client for IMX provider
91-
const guardianClient = new GuardianClient({
92-
config: walletConfig,
93-
getUser: (forceRefresh) => (forceRefresh ? auth.forceUserRefresh() : auth.getUser()),
94-
guardianApi: multiRollupApiClients.guardianApi,
95-
passportDomain: passportConfig.passportDomain,
96-
clientId: passportConfig.oidcConfiguration.clientId,
97-
});
98-
99-
const imxGuardianClient = new ImxGuardianClient({
100-
auth,
101-
guardianApi: multiRollupApiClients.guardianApi,
102-
confirmationScreen,
103-
crossSdkBridgeEnabled: passportModuleConfiguration.crossSdkBridgeEnabled || false,
104-
});
105-
106-
// Create Magic TEE signer for IMX provider
107-
const magicTeeApiClients = new MagicTeeApiClients({
108-
basePath: passportConfig.magicTeeBasePath,
109-
timeout: passportConfig.magicTeeTimeout,
110-
magicPublishableApiKey: passportConfig.magicPublishableApiKey,
111-
magicProviderId: passportConfig.magicProviderId,
112-
});
113-
const magicTEESigner = new MagicTEESigner(
114-
(forceRefresh) => (forceRefresh ? auth.forceUserRefresh() : auth.getUser()),
115-
magicTeeApiClients,
116-
);
117-
118-
const imxApiClients = buildImxApiClients(passportModuleConfiguration);
119-
120-
const passportImxProviderFactory = new PassportImxProviderFactory({
121-
auth,
122-
immutableXClient,
123-
magicTEESigner,
124-
passportEventEmitter: auth.eventEmitter,
125-
imxApiClients,
126-
guardianClient,
127-
imxGuardianClient,
128-
});
129-
13040
return {
13141
passportConfig,
13242
auth,
133-
passportImxProviderFactory,
13443
environment: passportModuleConfiguration.baseConfig.environment,
135-
// Keep walletConfig only for IMX GuardianClient
136-
walletConfig,
13744
};
13845
};
13946

@@ -142,11 +49,8 @@ export class Passport {
14249
// DEPENDENCIES & CONFIGURATION
14350
// ============================================================================
14451

145-
// Auth & Wallet (zkEVM uses these via public APIs)
14652
private readonly auth: Auth;
14753

148-
private readonly passportImxProviderFactory: PassportImxProviderFactory;
149-
15054
private readonly multiRollupApiClients: MultiRollupApiClients;
15155

15256
private readonly environment: Environment;
@@ -157,7 +61,6 @@ export class Passport {
15761
const privateVars = buildPrivateVars(passportModuleConfiguration);
15862

15963
this.auth = privateVars.auth;
160-
this.passportImxProviderFactory = privateVars.passportImxProviderFactory;
16164
this.passportConfig = privateVars.passportConfig;
16265
this.multiRollupApiClients = new MultiRollupApiClients(this.passportConfig.multiRollupConfig);
16366
this.environment = privateVars.environment;
@@ -166,42 +69,11 @@ export class Passport {
16669
}
16770

16871
// ============================================================================
169-
// IMX-SPECIFIC METHODS
170-
// ============================================================================
171-
172-
/**
173-
* Attempts to connect to IMX silently without user interaction.
174-
* @returns {Promise<IMXProvider | null>} A promise that resolves to an IMX provider if successful, or null if no cached session exists
175-
* @deprecated The method `login` with an argument of `{ useCachedSession: true }` should be used in conjunction with `connectImx` instead
176-
*/
177-
public async connectImxSilent(): Promise<IMXProvider | null> {
178-
return withMetricsAsync(
179-
() => this.passportImxProviderFactory.getProviderSilent(),
180-
'connectImxSilent',
181-
false,
182-
);
183-
}
184-
185-
/**
186-
* Connects to IMX, prompting user interaction if necessary.
187-
* @returns {Promise<IMXProvider>} A promise that resolves to an IMX provider
188-
*/
189-
public async connectImx(): Promise<IMXProvider> {
190-
return withMetricsAsync(
191-
() => this.passportImxProviderFactory.getProvider(),
192-
'connectImx',
193-
false,
194-
);
195-
}
196-
197-
// ============================================================================
198-
// ZKEVM-SPECIFIC METHODS
199-
// Uses Auth + Wallet packages
72+
// ZKEVM METHODS
20073
// ============================================================================
20174

20275
/**
20376
* Connects to EVM and optionally announces the provider.
204-
* Uses: Auth + Wallet packages
20577
* @param {Object} options - Configuration options
20678
* @param {boolean} options.announceProvider - Whether to announce the provider via EIP-6963 for wallet discovery (defaults to true)
20779
* @returns {Promise<Provider>} The EVM provider instance
@@ -277,14 +149,11 @@ export class Passport {
277149
}
278150

279151
// ============================================================================
280-
// SHARED METHODS (zkEVM + IMX)
281-
// Uses Auth class (public API)
282-
// Exception: forceUserRefresh for silent login (advanced operation)
152+
// AUTH METHODS
283153
// ============================================================================
284154

285155
/**
286-
* Logs in the user (works for both zkEVM and IMX).
287-
* Uses: Auth class
156+
* Logs in the user.
288157
* @param {Object} [options] - Login options
289158
* @param {boolean} [options.useCachedSession] - If true, attempts to use a cached session without user interaction.
290159
* @param {boolean} [options.useSilentLogin] - If true, attempts silent authentication without user interaction.
@@ -313,16 +182,14 @@ export class Passport {
313182

314183
/**
315184
* Handles the login callback from the authentication service.
316-
* Uses: Auth class
317185
* @returns {Promise<void>} A promise that resolves when the login callback is handled
318186
*/
319187
public async loginCallback(): Promise<void> {
320188
await this.auth.loginCallback();
321189
}
322190

323191
/**
324-
* Logs out the user (works for both zkEVM and IMX).
325-
* Uses: Auth class
192+
* Logs out the user.
326193
* @returns {Promise<void>} A promise that resolves when the user is logged out
327194
*/
328195
public async logout(): Promise<void> {
@@ -331,7 +198,6 @@ export class Passport {
331198

332199
/**
333200
* Retrieves the current user's information.
334-
* Uses: Auth class
335201
* @returns {Promise<UserProfile | undefined>} A promise that resolves to the user profile if logged in, undefined otherwise
336202
*/
337203
public async getUserInfo(): Promise<UserProfile | undefined> {
@@ -433,7 +299,7 @@ export class Passport {
433299
* @param {LinkWalletParams} params - Parameters for linking the wallet
434300
* @returns {Promise<LinkedWallet>} A promise that resolves to the linked wallet information
435301
* @throws {PassportError} If the user is not logged in (NOT_LOGGED_IN_ERROR)
436-
* - If the user is not registered with StarkEx (USER_NOT_REGISTERED_ERROR)
302+
* - If the user is not registered (USER_NOT_REGISTERED_ERROR)
437303
* - If the wallet is already linked (LINK_WALLET_ALREADY_LINKED_ERROR)
438304
* - If the maximum number of wallets are linked (LINK_WALLET_MAX_WALLETS_LINKED_ERROR)
439305
* - Duplicate nonce used (LINK_WALLET_DUPLICATE_NONCE_ERROR)
@@ -461,23 +327,7 @@ export class Passport {
461327
throw new PassportError('User is not logged in', PassportErrorType.NOT_LOGGED_IN_ERROR);
462328
}
463329

464-
const isRegisteredWithZkEvm = isUserZkEvm(user);
465-
const isRegisteredWithIMX = (() => {
466-
try {
467-
toUserImx(user);
468-
return true;
469-
} catch (imxError) {
470-
if (
471-
imxError instanceof PassportError
472-
&& imxError.type === PassportErrorType.USER_NOT_REGISTERED_ERROR
473-
) {
474-
return false;
475-
}
476-
throw imxError;
477-
}
478-
})();
479-
480-
if (!isRegisteredWithIMX && !isRegisteredWithZkEvm) {
330+
if (!isUserZkEvm(user)) {
481331
throw new PassportError('User has not been registered', PassportErrorType.USER_NOT_REGISTERED_ERROR);
482332
}
483333

0 commit comments

Comments
 (0)