Skip to content

Commit c262bd5

Browse files
authored
feat(auth): extract arbitrum chain data from passport claim (#2771)
1 parent c2dfa59 commit c262bd5

File tree

4 files changed

+132
-7
lines changed

4 files changed

+132
-7
lines changed

packages/auth/src/Auth.test.ts

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ describe('Auth', () => {
137137
});
138138
});
139139

140-
describe('username extraction', () => {
140+
describe('mapOidcUserToDomainModel', () => {
141141
it('extracts username from id token when present', () => {
142142
const mockOidcUser = {
143143
id_token: 'token',
@@ -158,6 +158,88 @@ describe('Auth', () => {
158158
expect(result.profile.username).toEqual('username123');
159159
});
160160

161+
it('extracts zkEvm chain data from passport metadata', () => {
162+
const mockOidcUser = {
163+
id_token: 'token',
164+
access_token: 'access',
165+
refresh_token: 'refresh',
166+
expired: false,
167+
profile: { sub: 'user-123', email: 'test@example.com', nickname: 'tester' },
168+
};
169+
170+
(decodeJwtPayload as jest.Mock).mockReturnValue({
171+
passport: {
172+
zkevm_eth_address: '0xzkevmaddress',
173+
zkevm_user_admin_address: '0xzkevmadmin',
174+
},
175+
});
176+
177+
const result = (Auth as any).mapOidcUserToDomainModel(mockOidcUser);
178+
179+
expect(result.zkEvm).toEqual({
180+
ethAddress: '0xzkevmaddress',
181+
userAdminAddress: '0xzkevmadmin',
182+
});
183+
});
184+
185+
it('extracts arbitrum_one chain data from nested passport metadata', () => {
186+
const mockOidcUser = {
187+
id_token: 'token',
188+
access_token: 'access',
189+
refresh_token: 'refresh',
190+
expired: false,
191+
profile: { sub: 'user-123', email: 'test@example.com', nickname: 'tester' },
192+
};
193+
194+
(decodeJwtPayload as jest.Mock).mockReturnValue({
195+
passport: {
196+
arbitrum_one: {
197+
eth_address: '0xarbaddress',
198+
user_admin_address: '0xarbadmin',
199+
},
200+
},
201+
});
202+
203+
const result = (Auth as any).mapOidcUserToDomainModel(mockOidcUser);
204+
205+
expect(result.arbitrum_one).toEqual({
206+
ethAddress: '0xarbaddress',
207+
userAdminAddress: '0xarbadmin',
208+
});
209+
});
210+
211+
it('extracts both zkEvm and arbitrum_one when present', () => {
212+
const mockOidcUser = {
213+
id_token: 'token',
214+
access_token: 'access',
215+
refresh_token: 'refresh',
216+
expired: false,
217+
profile: { sub: 'user-123', email: 'test@example.com', nickname: 'tester' },
218+
};
219+
220+
(decodeJwtPayload as jest.Mock).mockReturnValue({
221+
passport: {
222+
zkevm_eth_address: '0xzkevmaddress',
223+
zkevm_user_admin_address: '0xzkevmadmin',
224+
arbitrum_one: {
225+
eth_address: '0xarbaddress',
226+
user_admin_address: '0xarbadmin',
227+
},
228+
},
229+
});
230+
231+
const result = (Auth as any).mapOidcUserToDomainModel(mockOidcUser);
232+
233+
expect(result.zkEvm).toEqual({
234+
ethAddress: '0xzkevmaddress',
235+
userAdminAddress: '0xzkevmadmin',
236+
});
237+
expect(result.arbitrum_one).toEqual({
238+
ethAddress: '0xarbaddress',
239+
userAdminAddress: '0xarbadmin',
240+
});
241+
});
242+
161243
it('maps username when creating OIDC user from device tokens', () => {
162244
const tokenResponse = {
163245
id_token: 'token',

packages/auth/src/Auth.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
PassportMetadata,
3030
IdTokenPayload,
3131
isUserZkEvm,
32+
EvmChain,
3233
} from './types';
3334
import EmbeddedLoginPrompt from './login/embeddedLoginPrompt';
3435
import TypedEventEmitter from './utils/typedEventEmitter';
@@ -570,12 +571,25 @@ export class Auth {
570571
username,
571572
},
572573
};
574+
573575
if (passport?.zkevm_eth_address && passport?.zkevm_user_admin_address) {
574576
user.zkEvm = {
575577
ethAddress: passport.zkevm_eth_address,
576578
userAdminAddress: passport.zkevm_user_admin_address,
577579
};
578580
}
581+
582+
const chains = Object.values(EvmChain).filter((chain) => chain !== EvmChain.ZKEVM);
583+
for (const chain of chains) {
584+
const chainMetadata = passport?.[chain as Exclude<EvmChain, EvmChain.ZKEVM>];
585+
if (chainMetadata?.eth_address && chainMetadata?.user_admin_address) {
586+
user[chain] = {
587+
ethAddress: chainMetadata.eth_address,
588+
userAdminAddress: chainMetadata.user_admin_address,
589+
};
590+
}
591+
}
592+
579593
return user;
580594
};
581595

packages/auth/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@ export type {
1717
AuthModuleConfiguration,
1818
PopupOverlayOptions,
1919
PassportMetadata,
20+
PassportChainMetadata,
21+
ChainAddress,
2022
IdTokenPayload,
2123
PKCEData,
2224
AuthEventMap,
2325
} from './types';
2426
export {
25-
isUserZkEvm, RollupType, MarketingConsentStatus, AuthEvents,
27+
isUserZkEvm,
28+
RollupType,
29+
EvmChain,
30+
MarketingConsentStatus,
31+
AuthEvents,
2632
} from './types';
2733

2834
// Export TypedEventEmitter

packages/auth/src/types.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,45 @@ export enum RollupType {
1616
ZKEVM = 'zkEvm',
1717
}
1818

19+
/**
20+
* Supported EVM chains for user registration
21+
* Matches EvmChain from @imtbl/wallet but defined here to avoid circular dependency
22+
*/
23+
export enum EvmChain {
24+
ZKEVM = 'zkevm',
25+
ARBITRUM_ONE = 'arbitrum_one',
26+
}
27+
28+
export type ChainAddress = {
29+
ethAddress: string;
30+
userAdminAddress: string;
31+
};
32+
1933
export type User = {
2034
idToken?: string;
2135
accessToken: string;
2236
refreshToken?: string;
2337
profile: UserProfile;
2438
expired?: boolean;
25-
[RollupType.ZKEVM]?: {
26-
ethAddress: string;
27-
userAdminAddress: string;
28-
};
39+
[RollupType.ZKEVM]?: ChainAddress;
40+
} & {
41+
[K in Exclude<EvmChain, EvmChain.ZKEVM>]?: ChainAddress;
2942
};
3043

44+
export type PassportChainMetadata = {
45+
eth_address: string;
46+
user_admin_address: string;
47+
};
48+
49+
/**
50+
* Passport metadata
51+
* - zkEVM: flat fields (zkevm_eth_address, zkevm_user_admin_address)
52+
* - Other chains: nested objects (arbitrum_one: { eth_address, user_admin_address })
53+
*/
3154
export type PassportMetadata = {
3255
zkevm_eth_address?: string;
3356
zkevm_user_admin_address?: string;
34-
};
57+
} & Partial<Record<Exclude<EvmChain, EvmChain.ZKEVM>, PassportChainMetadata>>;
3558

3659
export interface OidcConfiguration {
3760
clientId: string;

0 commit comments

Comments
 (0)