@@ -29,6 +29,13 @@ import type {
2929 TurnkeyMetadata ,
3030 TurnkeyOAuthProvider ,
3131} from '@injectivelabs/wallet-base'
32+ import type {
33+ TurnkeyOauthProvider ,
34+ TurnkeyOAuth2Response ,
35+ TurnkeyOAuthConfirmResponse ,
36+ TurnkeyOAuth2ConfirmResponse ,
37+ TurnkeyLinkOAuthProviderResponse ,
38+ } from '../types.js'
3239
3340export class TurnkeyWallet {
3441 private otpId ?: string
@@ -359,7 +366,10 @@ export class TurnkeyWallet {
359366 )
360367 }
361368
362- public async confirmOAuth ( provider : TurnkeyOAuthProvider , oidcToken : string ) {
369+ public async confirmOAuth (
370+ provider : TurnkeyOAuthProvider ,
371+ oidcToken : string ,
372+ ) : Promise < TurnkeyOAuthConfirmResponse > {
363373 if ( provider === TurnkeyProvider . Apple ) {
364374 throw new WalletException (
365375 new Error ( 'Apple sign in option is currently not supported' ) ,
@@ -376,7 +386,16 @@ export class TurnkeyWallet {
376386 oauthLoginPath : this . metadata . oauthLoginPath || TURNKEY_OAUTH_PATH ,
377387 } )
378388
379- if ( ! oauthResult || ! oauthResult . credentialBundle ) {
389+ if (
390+ oauthResult &&
391+ 'status' in oauthResult &&
392+ ( oauthResult . status === 'link_required' ||
393+ oauthResult . status === 'existing_account_detected' )
394+ ) {
395+ return oauthResult
396+ }
397+
398+ if ( ! oauthResult ?. credentialBundle ) {
380399 throw new WalletException ( new Error ( 'Unexpected OAuth result' ) )
381400 }
382401
@@ -398,14 +417,18 @@ export class TurnkeyWallet {
398417 codeVerifier : string
399418 targetPublicKey : string
400419 providerName : TurnkeyOAuthProvider
401- } ) {
420+ } ) : Promise < TurnkeyOAuth2ConfirmResponse > {
402421 const indexedDbClient = await this . getIndexedDbClient ( )
403422 const path = this . metadata . oauth2ExchangePath || 'turnkey/oauth2'
404423
405424 const response = await this . client . post < {
406- data : { credentialBundle : string ; organizationId : string ; email ?: string }
425+ data : TurnkeyOAuth2Response
407426 } > ( path , { nonce, authCode, codeVerifier, targetPublicKey, providerName } )
408427
428+ if ( response ?. data ?. status === 'link_required' ) {
429+ return response . data
430+ }
431+
409432 if ( ! response ?. data ?. credentialBundle || ! response ?. data ?. organizationId ) {
410433 throw new WalletException (
411434 new Error ( `${ providerName } OAuth2 exchange failed` ) ,
@@ -421,6 +444,79 @@ export class TurnkeyWallet {
421444 return { session : credentialBundle , email }
422445 }
423446
447+ public async linkOAuthProvider ( {
448+ oidcToken,
449+ providerName,
450+ } : {
451+ oidcToken : string
452+ providerName : TurnkeyOAuthProvider
453+ } ) : Promise < TurnkeyLinkOAuthProviderResponse > {
454+ const indexedDbClient = await this . getIndexedDbClient ( )
455+ const { organizationId } = await this . getSession ( )
456+
457+ if ( ! organizationId ) {
458+ throw new WalletException (
459+ new Error ( 'Turnkey organization not found. Please login again.' ) ,
460+ )
461+ }
462+
463+ const user = await indexedDbClient . getWhoami ( { organizationId } )
464+ let userId = user ?. userId
465+
466+ if ( ! userId ) {
467+ const { users } = await indexedDbClient . getUsers ( { organizationId } )
468+
469+ if ( users . length !== 1 ) {
470+ throw new WalletException (
471+ new Error ( 'Unable to resolve current Turnkey user.' ) ,
472+ )
473+ }
474+
475+ userId = users [ 0 ] . userId
476+ }
477+
478+ await indexedDbClient . createOauthProviders ( {
479+ userId,
480+ organizationId,
481+ oauthProviders : [ { providerName, oidcToken } ] ,
482+ } )
483+
484+ return { organizationId }
485+ }
486+
487+ public async getCurrentOauthProviders ( ) : Promise < TurnkeyOauthProvider [ ] > {
488+ const indexedDbClient = await this . getIndexedDbClient ( )
489+ const { organizationId } = await this . getSession ( )
490+
491+ if ( ! organizationId ) {
492+ throw new WalletException (
493+ new Error ( 'Turnkey organization not found. Please login again.' ) ,
494+ )
495+ }
496+
497+ const user = await indexedDbClient . getWhoami ( { organizationId } )
498+ let userId = user ?. userId
499+
500+ if ( ! userId ) {
501+ const { users } = await indexedDbClient . getUsers ( { organizationId } )
502+
503+ if ( users . length !== 1 ) {
504+ throw new WalletException (
505+ new Error ( 'Unable to resolve current Turnkey user.' ) ,
506+ )
507+ }
508+
509+ userId = users [ 0 ] . userId
510+ }
511+
512+ const { oauthProviders } = await indexedDbClient . getOauthProviders ( {
513+ organizationId,
514+ userId,
515+ } )
516+
517+ return oauthProviders
518+ }
519+
424520 public async refreshSession ( ) {
425521 const session = await this . getSession ( )
426522 const indexedDbClient = await this . getIndexedDbClient ( )
0 commit comments