Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/wallets/wallet-turnkey/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './strategy/types.js'
export * from './strategy/strategy.js'

export * from './strategy/turnkey/turnkey.js'
Expand Down
8 changes: 3 additions & 5 deletions packages/wallets/wallet-turnkey/src/strategy/turnkey/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import type { HttpRestClient } from '@injectivelabs/utils'
import type { TurnkeyIndexedDbClient } from '@turnkey/sdk-browser'
import type { TurnkeyOAuthProvider } from '@injectivelabs/wallet-base'
import type { TurnkeyOauthLoginResponse } from '../types.js'
import type { TurnkeyOauthAuthenticatedResponse } from '../types.js'

export class TurnkeyOauthWallet {
static async generateOAuthNonce(indexedDbClient: TurnkeyIndexedDbClient) {
Expand Down Expand Up @@ -42,9 +42,7 @@ export class TurnkeyOauthWallet {
providerName: TurnkeyOAuthProvider
indexedDbClient: TurnkeyIndexedDbClient
expirationSeconds?: number
}): Promise<
{ organizationId: string; credentialBundle: string } | undefined
> {
}): Promise<TurnkeyOauthAuthenticatedResponse | undefined> {
const { client, indexedDbClient, expirationSeconds } = args

const path = args.oauthLoginPath || TURNKEY_OAUTH_PATH
Expand All @@ -57,7 +55,7 @@ export class TurnkeyOauthWallet {
}
// client.$post is undefined, resorting to this for now
const response = await client.post<{
data: TurnkeyOauthLoginResponse
data: TurnkeyOauthAuthenticatedResponse
}>(path, {
targetPublicKey,
oidcToken: args.oidcToken,
Expand Down
60 changes: 53 additions & 7 deletions packages/wallets/wallet-turnkey/src/strategy/turnkey/turnkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import type {
TurnkeyMetadata,
TurnkeyOAuthProvider,
} from '@injectivelabs/wallet-base'
import type {
TurnkeyOauthProvider,
TurnkeyOAuth2ConfirmResponse,
TurnkeyOAuth2AuthenticatedResponse,
} from '../types.js'

export class TurnkeyWallet {
private otpId?: string
Expand Down Expand Up @@ -359,7 +364,10 @@ export class TurnkeyWallet {
)
}

public async confirmOAuth(provider: TurnkeyOAuthProvider, oidcToken: string) {
public async confirmOAuth(
provider: TurnkeyOAuthProvider,
oidcToken: string,
): Promise<string> {
if (provider === TurnkeyProvider.Apple) {
throw new WalletException(
new Error('Apple sign in option is currently not supported'),
Expand All @@ -376,7 +384,7 @@ export class TurnkeyWallet {
oauthLoginPath: this.metadata.oauthLoginPath || TURNKEY_OAUTH_PATH,
})

if (!oauthResult || !oauthResult.credentialBundle) {
if (!oauthResult?.credentialBundle) {
throw new WalletException(new Error('Unexpected OAuth result'))
}

Expand All @@ -398,27 +406,65 @@ export class TurnkeyWallet {
codeVerifier: string
targetPublicKey: string
providerName: TurnkeyOAuthProvider
}) {
}): Promise<TurnkeyOAuth2ConfirmResponse> {
const indexedDbClient = await this.getIndexedDbClient()
const path = this.metadata.oauth2ExchangePath || 'turnkey/oauth2'

const response = await this.client.post<{
data: { credentialBundle: string; organizationId: string; email?: string }
data: TurnkeyOAuth2AuthenticatedResponse
}>(path, { nonce, authCode, codeVerifier, targetPublicKey, providerName })

if (!response?.data?.credentialBundle || !response?.data?.organizationId) {
const responseData = response?.data
const credentialBundle =
responseData?.credentialBundle ?? responseData?.session
const organizationId = responseData?.organizationId

if (!credentialBundle || !organizationId) {
throw new WalletException(
new Error(`${providerName} OAuth2 exchange failed`),
)
}

const { credentialBundle, organizationId, email } = response.data
const { email, userName, profileImageUrl } = responseData

await indexedDbClient.loginWithSession(credentialBundle)

this.userOrganizationId = organizationId

return { session: credentialBundle, email }
return { session: credentialBundle, email, userName, profileImageUrl }
}

public async getCurrentOauthProviders(): Promise<TurnkeyOauthProvider[]> {
const indexedDbClient = await this.getIndexedDbClient()
const { organizationId } = await this.getSession()

if (!organizationId) {
throw new WalletException(
new Error('Turnkey organization not found. Please login again.'),
)
}

const user = await indexedDbClient.getWhoami({ organizationId })
let userId = user?.userId

if (!userId) {
const { users } = await indexedDbClient.getUsers({ organizationId })

if (users.length !== 1) {
throw new WalletException(
new Error('Unable to resolve current Turnkey user.'),
)
}

userId = users[0].userId
}

const { oauthProviders } = await indexedDbClient.getOauthProviders({
organizationId,
userId,
})

return oauthProviders
}

public async refreshSession() {
Expand Down
28 changes: 26 additions & 2 deletions packages/wallets/wallet-turnkey/src/strategy/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,32 @@ export type TurnkeyConfirmEmailOTPResponse = {
organizationId: string
}

export type TurnkeyOauthLoginResponse = {
export type TurnkeyOauthAuthenticatedResponse = {
message?: string
organizationId: string
credentialBundle: string
message: string
}

export type TurnkeyOAuth2AuthenticatedResponse = {
email?: string
session?: string
userName?: string
profileImageUrl?: string
organizationId: string
credentialBundle?: string
}

export type TurnkeyOAuth2ConfirmResponse = {
email?: string
session: string
userName?: string
profileImageUrl?: string
}

export type TurnkeyOauthProvider = {
issuer: string
subject: string
audience: string
providerId: string
providerName: string
}