-
Notifications
You must be signed in to change notification settings - Fork 476
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Winston Yeo <[email protected]>
- Loading branch information
1 parent
1335852
commit 06e4f34
Showing
22 changed files
with
1,910 additions
and
20 deletions.
There are no files selected for viewing
118 changes: 118 additions & 0 deletions
118
packages/thirdweb/src/wallets/embedded/core/authentication/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import type { ThirdwebClient } from "../../../../index.js"; | ||
import type { AuthArgsType, PreAuthArgsType } from "./type.js"; | ||
import { AuthProvider } from "../../implementations/interfaces/auth.js"; | ||
import { UserWalletStatus } from "../../implementations/interfaces/embedded-wallets/embedded-wallets.js"; | ||
import type { EmbeddedWalletSdk } from "../../implementations/lib/embedded-wallet.js"; | ||
|
||
const ewsSDKCache = new Map<ThirdwebClient, EmbeddedWalletSdk>(); | ||
|
||
/** | ||
* @internal | ||
*/ | ||
async function getEmbeddedWalletSDK(client: ThirdwebClient) { | ||
if (ewsSDKCache.has(client)) { | ||
return ewsSDKCache.get(client) as EmbeddedWalletSdk; | ||
} | ||
const { EmbeddedWalletSdk } = await import( | ||
"../../implementations/lib/embedded-wallet.js" | ||
); | ||
// TODO (ew) cache this | ||
const ewSDK = new EmbeddedWalletSdk({ | ||
client: client, | ||
}); | ||
ewsSDKCache.set(client, ewSDK); | ||
return ewSDK; | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export async function getAuthenticatedUser(args: { client: ThirdwebClient }) { | ||
const { client } = args; | ||
const ewSDK = await getEmbeddedWalletSDK(client); | ||
const user = await ewSDK.getUser(); | ||
switch (user.status) { | ||
case UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED: { | ||
return user; | ||
} | ||
} | ||
return undefined; | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export async function preAuthenticate(args: PreAuthArgsType) { | ||
const ewSDK = await getEmbeddedWalletSDK(args.client); | ||
const strategy = args.strategy; | ||
switch (strategy) { | ||
case "email": { | ||
return ewSDK.auth.sendEmailLoginOtp({ email: args.email }); | ||
} | ||
default: | ||
throw new Error( | ||
`Provider: ${strategy} doesnt require pre-authentication`, | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export async function authenticate(args: AuthArgsType) { | ||
const ewSDK = await getEmbeddedWalletSDK(args.client); | ||
const strategy = args.strategy; | ||
switch (strategy) { | ||
case "email": { | ||
return await ewSDK.auth.verifyEmailLoginOtp({ | ||
email: args.email, | ||
otp: args.verificationCode, | ||
}); | ||
} | ||
case "apple": | ||
case "facebook": | ||
case "google": { | ||
const oauthProvider = oauthStrategyToAuthProvider[strategy]; | ||
return ewSDK.auth.loginWithOauth({ | ||
oauthProvider, | ||
closeOpenedWindow: args.closeOpenedWindow, | ||
openedWindow: args.openedWindow, | ||
}); | ||
} | ||
case "jwt": { | ||
return ewSDK.auth.loginWithCustomJwt({ | ||
jwt: args.jwt, | ||
encryptionKey: args.encryptionKey, | ||
}); | ||
} | ||
case "auth_endpoint": { | ||
return ewSDK.auth.loginWithCustomAuthEndpoint({ | ||
payload: args.payload, | ||
encryptionKey: args.encryptionKey, | ||
}); | ||
} | ||
case "iframe_email_verification": { | ||
return ewSDK.auth.loginWithEmailOtp({ | ||
email: args.email, | ||
}); | ||
} | ||
case "iframe": { | ||
return ewSDK.auth.loginWithModal(); | ||
} | ||
default: | ||
assertUnreachable(strategy); | ||
} | ||
} | ||
|
||
function assertUnreachable(x: never): never { | ||
throw new Error("Invalid param: " + x); | ||
} | ||
|
||
const oauthStrategyToAuthProvider: Record< | ||
"google" | "facebook" | "apple", | ||
AuthProvider | ||
> = { | ||
google: AuthProvider.GOOGLE, | ||
facebook: AuthProvider.FACEBOOK, | ||
apple: AuthProvider.APPLE, | ||
}; |
37 changes: 37 additions & 0 deletions
37
packages/thirdweb/src/wallets/embedded/core/authentication/type.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import type { ThirdwebClient } from "../../../../client/client.js"; | ||
|
||
export type MultiStepAuthProviderType = { | ||
strategy: "email"; | ||
email: string; | ||
}; | ||
export type PreAuthArgsType = MultiStepAuthProviderType & { | ||
client: ThirdwebClient; | ||
}; | ||
|
||
export type MultiStepAuthArgsType = MultiStepAuthProviderType & { | ||
verificationCode: string; | ||
}; | ||
export type SingleStepAuthArgsType = | ||
| { | ||
strategy: "google"; | ||
openedWindow?: Window; | ||
closeOpenedWindow?: (window: Window) => void; | ||
} | ||
| { | ||
strategy: "apple"; | ||
openedWindow?: Window; | ||
closeOpenedWindow?: (window: Window) => void; | ||
} | ||
| { | ||
strategy: "facebook"; | ||
openedWindow?: Window; | ||
closeOpenedWindow?: (window: Window) => void; | ||
} | ||
| { strategy: "jwt"; jwt: string; encryptionKey: string } | ||
| { strategy: "auth_endpoint"; payload: string; encryptionKey: string } | ||
| { strategy: "iframe_email_verification"; email: string } | ||
| { strategy: "iframe" }; | ||
|
||
export type AuthArgsType = (MultiStepAuthArgsType | SingleStepAuthArgsType) & { | ||
client: ThirdwebClient; | ||
}; |
100 changes: 100 additions & 0 deletions
100
packages/thirdweb/src/wallets/embedded/core/wallet/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { | ||
defineChain, | ||
type Chain, | ||
type ThirdwebClient, | ||
} from "../../../../index.js"; | ||
import type { Account, Wallet } from "../../../interfaces/wallet.js"; | ||
import type { WalletMetadata } from "../../../types.js"; | ||
import type { | ||
MultiStepAuthArgsType, | ||
PreAuthArgsType, | ||
SingleStepAuthArgsType, | ||
} from "../authentication/type.js"; | ||
import { | ||
authenticate, | ||
getAuthenticatedUser, | ||
preAuthenticate, | ||
} from "../authentication/index.js"; | ||
import type { EmbeddedWalletConfig } from "./types.js"; | ||
|
||
/** | ||
* Embedded Wallet | ||
* @param args - The args to use for the wallet | ||
* @param args.client - The ThirdwebClient to use for the wallet | ||
* @returns The embedded wallet | ||
* @example | ||
* ```ts | ||
* import { embeddedWallet } from "thirdweb/wallets"; | ||
* | ||
* const wallet = embeddedWallet({ | ||
* client, | ||
* }); | ||
* await wallet.connect({ | ||
* strategy: "google", | ||
* }); | ||
* ``` | ||
*/ | ||
export function embeddedWallet(args: EmbeddedWalletConfig) { | ||
return new EmbeddedWallet(args); | ||
} | ||
|
||
class EmbeddedWallet implements Wallet { | ||
metadata: WalletMetadata = { | ||
id: "embedded-wallet", | ||
name: "Embedded Wallet", | ||
iconUrl: "", // TODO (ew) | ||
}; | ||
client: ThirdwebClient; | ||
account?: Account; | ||
chain: Chain; | ||
|
||
constructor(args: EmbeddedWalletConfig) { | ||
this.client = args.client; | ||
this.chain = args.defaultChain ?? defineChain(1); | ||
} | ||
|
||
async preAuthenticate(options: Omit<PreAuthArgsType, "client">) { | ||
return preAuthenticate({ | ||
client: this.client, | ||
...options, | ||
}); | ||
} | ||
|
||
async connect( | ||
options: MultiStepAuthArgsType | SingleStepAuthArgsType, | ||
): Promise<Account> { | ||
const authResult = await authenticate({ | ||
client: this.client, | ||
...options, | ||
}); | ||
const authAccount = await authResult.user.wallet.getAccount(); | ||
this.account = authAccount; | ||
return authAccount; | ||
} | ||
|
||
async autoConnect(): Promise<Account> { | ||
const user = await getAuthenticatedUser({ client: this.client }); | ||
if (!user) { | ||
throw new Error("not authenticated"); | ||
} | ||
const authAccount = await user.wallet.getAccount(); | ||
this.account = authAccount; | ||
return authAccount; | ||
} | ||
|
||
async disconnect(): Promise<void> { | ||
this.account = undefined; | ||
} | ||
|
||
getAccount(): Account | undefined { | ||
return this.account; | ||
} | ||
|
||
getChain() { | ||
return this.chain; | ||
} | ||
|
||
async switchChain(newChain: Chain) { | ||
this.chain = newChain; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import type { Chain } from "../../../../chains/types.js"; | ||
import type { ThirdwebClient } from "../../../../client/client.js"; | ||
|
||
export type EmbeddedWalletConfig = { | ||
client: ThirdwebClient; | ||
defaultChain?: Chain; | ||
}; |
68 changes: 68 additions & 0 deletions
68
packages/thirdweb/src/wallets/embedded/implementations/constants/settings.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/** | ||
* @internal | ||
*/ | ||
export const EMBEDDED_WALLET_PATH = "/sdk/2022-08-12/embedded-wallet"; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export const HEADLESS_GOOGLE_OAUTH_ROUTE = `/auth/headless-google-login-managed`; | ||
/** | ||
* @internal | ||
*/ | ||
export const GET_IFRAME_BASE_URL = () => { | ||
if ( | ||
!!( | ||
typeof window !== "undefined" && | ||
localStorage.getItem("IS_THIRDWEB_DEV") === "true" | ||
) | ||
) { | ||
return ( | ||
window.localStorage.getItem("THIRDWEB_DEV_URL") ?? "http://localhost:3000" | ||
); | ||
} | ||
|
||
return `https://embedded-wallet.thirdweb.com`; | ||
}; | ||
/** | ||
* @internal | ||
*/ | ||
export const WALLET_USER_DETAILS_LOCAL_STORAGE_NAME = (clientId: string) => | ||
`thirdwebEwsWalletUserDetails-${clientId}`; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export const WALLET_USER_ID_LOCAL_STORAGE_NAME = (clientId: string) => | ||
`thirdwebEwsWalletUserId-${clientId}`; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
const AUTH_TOKEN_LOCAL_STORAGE_PREFIX = "walletToken"; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export const AUTH_TOKEN_LOCAL_STORAGE_NAME = (clientId: string) => { | ||
return `${AUTH_TOKEN_LOCAL_STORAGE_PREFIX}-${clientId}`; | ||
}; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
const DEVICE_SHARE_LOCAL_STORAGE_PREFIX = "a"; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export const DEVICE_SHARE_LOCAL_STORAGE_NAME = ( | ||
clientId: string, | ||
userId: string, | ||
) => `${DEVICE_SHARE_LOCAL_STORAGE_PREFIX}-${clientId}-${userId}`; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export const DEVICE_SHARE_LOCAL_STORAGE_NAME_DEPRECATED = (clientId: string) => | ||
`${DEVICE_SHARE_LOCAL_STORAGE_PREFIX}-${clientId}`; |
34 changes: 34 additions & 0 deletions
34
packages/thirdweb/src/wallets/embedded/implementations/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
export { | ||
AUTH_TOKEN_LOCAL_STORAGE_NAME, | ||
DEVICE_SHARE_LOCAL_STORAGE_NAME, | ||
DEVICE_SHARE_LOCAL_STORAGE_NAME_DEPRECATED, | ||
WALLET_USER_DETAILS_LOCAL_STORAGE_NAME, | ||
WALLET_USER_ID_LOCAL_STORAGE_NAME, | ||
} from "./constants/settings.js"; | ||
export { AuthProvider, RecoveryShareManagement } from "./interfaces/auth.js"; | ||
export type { | ||
AuthAndWalletRpcReturnType, | ||
AuthLoginReturnType, | ||
AuthStoredTokenWithCookieReturnType, | ||
StoredTokenType, | ||
GetHeadlessLoginLinkReturnType, | ||
} from "./interfaces/auth.js"; | ||
export { UserWalletStatus } from "./interfaces/embedded-wallets/embedded-wallets.js"; | ||
export type { | ||
AuthDetails, | ||
EmbeddedWalletConstructorType, | ||
GetAuthDetailsReturnType, | ||
GetUser, | ||
GetUserWalletStatusRpcReturnType, | ||
InitializedUser, | ||
LogoutReturnType, | ||
SendEmailOtpReturnType, | ||
SetUpWalletRpcReturnType, | ||
} from "./interfaces/embedded-wallets/embedded-wallets.js"; | ||
export type { | ||
GetAddressReturnType, | ||
SignMessageReturnType, | ||
SignTransactionReturnType, | ||
SignedTypedDataReturnType, | ||
} from "./interfaces/embedded-wallets/signer.js"; | ||
export { EmbeddedWalletSdk } from "./lib/embedded-wallet.js"; |
Oops, something went wrong.