Skip to content

Commit c717923

Browse files
fix(passport): remove toUserImx validation from registerOffchain (#2766)
1 parent 0b33fdf commit c717923

File tree

2 files changed

+142
-1
lines changed

2 files changed

+142
-1
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { IMXClient } from '@imtbl/x-client';
2+
import { ImxApiClients, imx } from '@imtbl/generated-clients';
3+
import { Auth, User } from '@imtbl/auth';
4+
import { GuardianClient, MagicTEESigner } from '@imtbl/wallet';
5+
import { PassportImxProvider } from './passportImxProvider';
6+
import { ImxGuardianClient } from './imxGuardianClient';
7+
import registerOffchain from './workflows/registerOffchain';
8+
import { getStarkSigner } from './getStarkSigner';
9+
import { PassportError, PassportErrorType } from '../errors/passportError';
10+
11+
jest.mock('./workflows/registerOffchain');
12+
jest.mock('./getStarkSigner');
13+
14+
describe('PassportImxProvider', () => {
15+
let provider: PassportImxProvider;
16+
let mockAuth: jest.Mocked<Auth>;
17+
let mockMagicTEESigner: jest.Mocked<MagicTEESigner>;
18+
let mockImxApiClients: ImxApiClients;
19+
let mockGuardianClient: jest.Mocked<GuardianClient>;
20+
let mockImxGuardianClient: jest.Mocked<ImxGuardianClient>;
21+
22+
// Mock user WITHOUT IMX metadata (new user)
23+
const mockUserWithoutImx: User = {
24+
expired: false,
25+
idToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnb29nbGUtb2F1dGgyfDEyMzQ1NiIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsInBhc3Nwb3J0Ijp7fX0.test',
26+
accessToken: 'access-token-123',
27+
refreshToken: 'refresh-token-123',
28+
profile: {
29+
sub: 'google-oauth2|123456',
30+
email: 'user@example.com',
31+
nickname: 'testuser',
32+
},
33+
};
34+
35+
// Mock user WITH IMX metadata (already registered)
36+
const mockUserWithImx: User = {
37+
...mockUserWithoutImx,
38+
idToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnb29nbGUtb2F1dGgyfDEyMzQ1NiIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsInBhc3Nwb3J0Ijp7ImlteFfldGhfYWRkcmVzcyI6IjB4YWJjIiwiaW14X3N0YXJrX2FkZHJlc3MiOiIweDc4OSIsImlteFf1c2VyX2FkbWluX2FkZHJlc3MiOiIweGRlZiJ9fQ.test',
39+
};
40+
41+
beforeEach(() => {
42+
mockAuth = {
43+
getUser: jest.fn(),
44+
forceUserRefresh: jest.fn(),
45+
eventEmitter: {
46+
on: jest.fn(),
47+
off: jest.fn(),
48+
emit: jest.fn(),
49+
} as any,
50+
} as any;
51+
52+
mockMagicTEESigner = {
53+
getAddress: jest.fn().mockResolvedValue('0xmagic'),
54+
} as any;
55+
56+
mockImxApiClients = new ImxApiClients({} as any);
57+
mockGuardianClient = {} as any;
58+
mockImxGuardianClient = {} as any;
59+
60+
const mockStarkSigner = {
61+
getAddress: jest.fn().mockResolvedValue('0xstark'),
62+
signMessage: jest.fn(),
63+
};
64+
(getStarkSigner as jest.Mock).mockResolvedValue(mockStarkSigner);
65+
66+
provider = new PassportImxProvider({
67+
auth: mockAuth,
68+
immutableXClient: new IMXClient({ baseConfig: {} as any }),
69+
passportEventEmitter: mockAuth.eventEmitter as any,
70+
magicTEESigner: mockMagicTEESigner,
71+
imxApiClients: mockImxApiClients,
72+
guardianClient: mockGuardianClient,
73+
imxGuardianClient: mockImxGuardianClient,
74+
});
75+
});
76+
77+
afterEach(() => {
78+
jest.clearAllMocks();
79+
});
80+
81+
describe('registerOffchain', () => {
82+
describe('when user is NEW (no IMX metadata)', () => {
83+
it('should successfully register new user without throwing error', async () => {
84+
// Arrange: User just logged in, NO IMX metadata yet
85+
mockAuth.getUser.mockResolvedValue(mockUserWithoutImx);
86+
87+
const mockRegisterResponse: imx.RegisterUserResponse = {
88+
tx_hash: '0xabc123',
89+
};
90+
(registerOffchain as jest.Mock).mockResolvedValue(mockRegisterResponse);
91+
92+
// Act
93+
const result = await provider.registerOffchain();
94+
95+
// Assert: Should succeed without throwing
96+
expect(result).toEqual(mockRegisterResponse);
97+
98+
// Verify workflow was called with User (not UserImx)
99+
expect(registerOffchain).toHaveBeenCalledWith(
100+
mockMagicTEESigner,
101+
expect.anything(), // starkSigner
102+
mockUserWithoutImx, // User without IMX metadata
103+
mockAuth,
104+
mockImxApiClients,
105+
);
106+
});
107+
});
108+
109+
describe('when user is ALREADY registered (has IMX metadata)', () => {
110+
it('should call workflow successfully', async () => {
111+
// Arrange: User already has IMX metadata
112+
mockAuth.getUser.mockResolvedValue(mockUserWithImx);
113+
114+
const mockRegisterResponse: imx.RegisterUserResponse = {
115+
tx_hash: '',
116+
};
117+
(registerOffchain as jest.Mock).mockResolvedValue(mockRegisterResponse);
118+
119+
// Act
120+
const result = await provider.registerOffchain();
121+
122+
// Assert
123+
expect(result).toEqual(mockRegisterResponse);
124+
expect(registerOffchain).toHaveBeenCalled();
125+
});
126+
});
127+
});
128+
129+
describe('getAddress', () => {
130+
it('should throw error when user has no IMX metadata', async () => {
131+
mockAuth.getUser.mockResolvedValue(mockUserWithoutImx);
132+
133+
await expect(provider.getAddress()).rejects.toThrow(
134+
new PassportError(
135+
'User has not been registered with StarkEx',
136+
PassportErrorType.USER_NOT_REGISTERED_ERROR,
137+
),
138+
);
139+
});
140+
});
141+
});

packages/passport/sdk/src/starkEx/passportImxProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export class PassportImxProvider implements IMXProvider {
181181
return await registerOffchain(
182182
this.magicTEESigner,
183183
starkSigner,
184-
toUserImx(user),
184+
user,
185185
this.auth,
186186
this.imxApiClients,
187187
);

0 commit comments

Comments
 (0)