UNPKG

@privy-io/react-auth

Version:

React client for the Privy Auth API

1,251 lines (1,236 loc) • 101 kB
import { createCoinbaseWalletSDK } from '@coinbase/wallet-sdk'; import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/browser'; import { Rpc, SolanaRpcApi, RpcSubscriptions, SolanaRpcSubscriptionsApi } from '@solana/kit'; import { ReactElement, ReactNode } from 'react'; import { Hex } from 'viem'; import { OAuthProviderID, AppResponse, SmartWalletType, PasskeyAuthenticateRequestBody, CustomOAuthProviderID, WalletChainType, User as User$1 } from '@privy-io/api-types'; import { CountryCode, Chain, ConnectedStandardSolanaWallet, RpcConfig, ChainLikeWithId } from '@privy-io/js-sdk-core'; import { createBaseAccountSDK } from '@base-org/account'; import { WalletWithFeatures, Wallet as Wallet$1 } from '@wallet-standard/base'; import { SolanaSignMessageFeature, SolanaSignTransactionFeature, SolanaSignAndSendTransactionFeature, SolanaSignInFeature } from '@solana/wallet-standard-features'; import { StandardConnectFeature, StandardDisconnectFeature, StandardEventsFeature } from '@wallet-standard/features'; import EventEmitter from 'eventemitter3'; /** * Internationalization strings for Privy UI components. * * Keys follow the pattern: `component.semanticDescription` */ type PrivyI18nStrings = { 'connectionStatus.successfullyConnected': string; 'connectionStatus.errorTitle': string; 'connectionStatus.connecting': string; 'connectionStatus.connectOneWallet': string; 'connectionStatus.checkOtherWindows': string; 'connectionStatus.stillHere': string; 'connectionStatus.tryConnectingAgain': string; 'connectionStatus.or': string; 'connectionStatus.useDifferentLink': string; 'connectWallet.connectYourWallet': string; 'connectWallet.waitingForWallet': string; 'connectWallet.connectToAccount': string; 'connectWallet.installAndConnect': string; 'connectWallet.tryConnectingAgain': string; 'connectWallet.openInApp': string; 'connectWallet.copyLink': string; 'connectWallet.retry': string; 'connectWallet.searchPlaceholder': string; 'connectWallet.noWalletsFound': string; 'connectWallet.lastUsed': string; 'connectWallet.selectYourWallet': string; 'connectWallet.selectNetwork': string; 'connectWallet.goToWallet': string; 'connectWallet.scanToConnect': string; 'connectWallet.openOrInstall': string; }; interface ConnectorEvents { walletsUpdated(): void; initialized(): void; } /** * @hidden * * A WalletConnector is identified by a connectorType and walletClientType. A * connectorType includes injected, wallet_connect, etc. A walletClientType * includes metamask, trustwallet, etc. * * Each WalletConnector manages a list of wallets, identified by an address * and chainId. Each wallet has a connected property indicating its current * connection status, which is determined based on events emitted by the * underlying provider. * * The WalletConnector also emits two events: walletsUpdated and initialized. * The walletsUpdated event is triggered when the list of wallets changes, * while the initialized event is triggered when the WalletConnector is * ready and has successfully executed the syncAccounts() function for * the first time. */ declare abstract class WalletConnector extends EventEmitter<ConnectorEvents> { connected: boolean; initialized: boolean; walletClientType: WalletClientType; abstract wallets: (BaseConnectedEthereumWallet | BaseConnectedSolanaWallet)[]; abstract chainType: 'ethereum' | 'solana'; abstract connectorType: ConnectorType; constructor(walletClientType: WalletClientType); abstract isConnected(): Promise<boolean>; abstract subscribeListeners(): void; abstract unsubscribeListeners(): void; abstract get walletBranding(): WalletBranding; abstract initialize(): Promise<void>; abstract connect(options: { showPrompt?: boolean; chainId?: number; }): Promise<BaseConnectedWallet | null>; abstract disconnect(): void; abstract promptConnection(walletClientType: WalletClientType): void; } /** * We support a subset of the provider methods found here: * * https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods * * For now, we're focused on signing-related methods because the iframe (this code) * is the only place that has access to the private key and thus is the only one * who can create signatures. All other methods do not need the private key and * can therefore be implemented by clients of the iframe. */ declare const SUPPORTED_ETHEREUM_RPC_METHODS: readonly ["eth_sign", "eth_populateTransactionRequest", "eth_signTransaction", "personal_sign", "eth_signTypedData_v4", "csw_signUserOperation", "secp256k1_sign"]; type EthereumRpcMethodType = (typeof SUPPORTED_ETHEREUM_RPC_METHODS)[number]; declare const SUPPORTED_SOLANA_RPC_METHODS: string[]; type SolanaRpcMethodType = (typeof SUPPORTED_SOLANA_RPC_METHODS)[number]; type Quantity = string | number | bigint; type UnsignedTransactionRequest = { from?: string; to?: string; nonce?: Quantity; gasLimit?: Quantity; gasPrice?: Quantity; data?: ArrayLike<number> | string; value?: Quantity; chainId?: number; type?: number; accessList?: Array<{ address: string; storageKeys: Array<string>; }> | Array<[string, Array<string>]> | Record<string, Array<string>>; maxPriorityFeePerGas?: Quantity; maxFeePerGas?: Quantity; }; type TransactionLog = { blockNumber: number; blockHash: string; transactionIndex: number; removed: boolean; address: string; data: string; topics: Array<string>; transactionHash: string; logIndex: number; }; type TransactionReceipt = { to: string; from: string; contractAddress: string; transactionIndex: number; root?: string; logs: Array<TransactionLog>; logsBloom: string; blockHash: string; transactionHash: string; blockNumber: number; confirmations: number; byzantium: boolean; type: number; status?: number; gasUsed: string; cumulativeGasUsed: string; effectiveGasPrice?: string; }; interface BaseEthereumRpcRequestType { method: EthereumRpcMethodType; } interface BaseSolanaRpcRequestType { method: SolanaRpcMethodType; } interface eth_populateTransactionRequest extends BaseEthereumRpcRequestType { method: 'eth_populateTransactionRequest'; params: [UnsignedTransactionRequest]; } interface eth_populateTransactionRequestResponse { method: 'eth_populateTransactionRequest'; data: UnsignedTransactionRequest; } interface eth_signTransaction extends BaseEthereumRpcRequestType { method: 'eth_signTransaction'; params: [UnsignedTransactionRequest]; } interface eth_sign extends BaseEthereumRpcRequestType { method: 'eth_sign'; params: [address: string, message: string]; } interface eth_signResponse { method: 'eth_sign'; data: string; } interface personal_sign extends BaseEthereumRpcRequestType { method: 'personal_sign'; params: [string, string]; } interface personal_signResponse { method: 'personal_sign'; data: string; } interface eth_signTransactionResponse { method: 'eth_signTransaction'; data: string; } interface eth_signTypedData_v4 extends BaseEthereumRpcRequestType { method: 'eth_signTypedData_v4'; params: [string, TypedMessage<MessageTypes> | string]; } interface eth_signTypedData_v4Response { method: 'eth_signTypedData_v4'; data: string; } interface secp256k1_sign extends BaseEthereumRpcRequestType { method: 'secp256k1_sign'; params: [`0x${string}`]; } interface secp256k1_signResponse { method: 'secp256k1_sign'; data: `0x${string}`; } interface solana_signMessage extends BaseSolanaRpcRequestType { method: 'signMessage'; params: { message: string; }; } interface solana_signMessageResponse { method: 'signMessage'; data: { signature: string; }; } type EthereumRpcRequestType = eth_signTransaction | eth_populateTransactionRequest | eth_sign | personal_sign | eth_signTypedData_v4 | secp256k1_sign; type EthereumRpcResponseType = eth_signTransactionResponse | eth_populateTransactionRequestResponse | eth_signResponse | personal_signResponse | eth_signTypedData_v4Response | secp256k1_signResponse; type SolanaRpcRequestType = solana_signMessage; type SolanaRpcResponseType = solana_signMessageResponse; declare abstract class PrivyError extends Error { /** * Privy error type. */ abstract type: string; /** * Original Error object, it the error originated client-side. */ cause?: Error; /** * An optional error code, often included in Privy API responses. */ privyErrorCode?: PrivyErrorCode; /** * @param type Privy error type. * @param message Human-readable message. * @param cause Source of this error. */ protected constructor(message: string, cause?: unknown, privyErrorCode?: PrivyErrorCode); toString(): string; } /** * The PrivyConnector instance threw an exception. */ declare class PrivyConnectorError extends PrivyError { type: string; constructor(message: string, cause?: unknown, privyErrorCode?: PrivyErrorCode); } declare enum PrivyErrorCode { OAUTH_ACCOUNT_SUSPENDED = "oauth_account_suspended", MISSING_OR_INVALID_PRIVY_APP_ID = "missing_or_invalid_privy_app_id", MISSING_OR_INVALID_PRIVY_ACCOUNT_ID = "missing_or_invalid_privy_account_id", MISSING_OR_INVALID_TOKEN = "missing_or_invalid_token", INVALID_DATA = "invalid_data", INVALID_CAPTCHA = "invalid_captcha", LINKED_TO_ANOTHER_USER = "linked_to_another_user", CANNOT_LINK_MORE_OF_TYPE = "cannot_link_more_of_type", FAILED_TO_LINK_ACCOUNT = "failed_to_link_account", FAILED_TO_UPDATE_ACCOUNT = "failed_to_update_account", USER_EXITED_UPDATE_FLOW = "exited_update_flow", ALLOWLIST_REJECTED = "allowlist_rejected", OAUTH_USER_DENIED = "oauth_user_denied", OAUTH_UNEXPECTED = "oauth_unexpected", UNKNOWN_AUTH_ERROR = "unknown_auth_error", USER_EXITED_AUTH_FLOW = "exited_auth_flow", USER_EXITED_LINK_FLOW = "exited_link_flow", USER_EXITED_SET_PASSWORD_FLOW = "user_exited_set_password_flow", MUST_BE_AUTHENTICATED = "must_be_authenticated", UNKNOWN_CONNECT_WALLET_ERROR = "unknown_connect_wallet_error", GENERIC_CONNECT_WALLET_ERROR = "generic_connect_wallet_error", CLIENT_REQUEST_TIMEOUT = "client_request_timeout", INVALID_CREDENTIALS = "invalid_credentials", MISSING_MFA_CREDENTIALS = "missing_or_invalid_mfa", UNKNOWN_MFA_ERROR = "unknown_mfa_error", EMBEDDED_WALLET_ALREADY_EXISTS = "embedded_wallet_already_exists", EMBEDDED_WALLET_NOT_FOUND = "embedded_wallet_not_found", EMBEDDED_WALLET_CREATE_ERROR = "embedded_wallet_create_error", UNKNOWN_EMBEDDED_WALLET_ERROR = "unknown_embedded_wallet_error", EMBEDDED_WALLET_PASSWORD_UNCONFIRMED = "embedded_wallet_password_unconfirmed", EMBEDDED_WALLET_PASSWORD_ALREADY_EXISTS = "embedded_wallet_password_already_exists", EMBEDDED_WALLET_RECOVERY_ALREADY_EXISTS = "embedded_wallet_recovery_already_exists", TRANSACTION_FAILURE = "transaction_failure", UNSUPPORTED_CHAIN_ID = "unsupported_chain_id", NOT_SUPPORTED = "not_supported", CAPTCHA_TIMEOUT = "captcha_timeout", INVALID_MESSAGE = "invalid_message", UNABLE_TO_SIGN = "unable_to_sign", CAPTCHA_FAILURE = "captcha_failure", CAPTCHA_DISABLED = "captcha_disabled", SESSION_STORAGE_UNAVAILABLE = "session_storage_unavailable", TOO_MANY_REQUESTS = "too_many_requests", USER_LIMIT_REACHED = "max_accounts_reached", DISALLOWED_LOGIN_METHOD = "disallowed_login_method", DISALLOWED_PLUS_EMAIL = "disallowed_plus_email", PASSKEY_NOT_ALLOWED = "passkey_not_allowed", USER_DOES_NOT_EXIST = "user_does_not_exist", INSUFFICIENT_BALANCE = "insufficient_balance", ACCOUNT_TRANSFER_REQUIRED = "account_transfer_required", BUFFER_NOT_DEFINED = "buffer_not_defined", UNSUPPORTED_WALLET_TYPE = "unsupported_wallet_type", NO_SOLANA_ACCOUNTS = "no_solana_accounts", UNKNOWN_FUNDING_ERROR = "unknown_funding_error" } declare class WalletTimeoutError extends PrivyConnectorError { type: string; constructor(); } /** * A ProviderRpcError combines the necessary bits of the {PrivyError} with the * EIP-compliant ProviderRpcError. This is meant to be a type around errors raised * by the ethereum provider. */ declare class ProviderRpcError extends PrivyError { type: string; readonly code: number; readonly data?: unknown; constructor(message: string, code: number, data?: unknown); } type ProviderConnectInfo = { chainId: string; }; type OnConnectEventHandler = (connectInfo: ProviderConnectInfo) => void; type OnDisconnectEventHandler = (error: ProviderRpcError) => void; type OnChainChangedEventHandler = (chainId: string | number) => void; type OnAccountsChangedEventHandler = (accounts: string[]) => void; type ProviderMessage = { type: string; data: unknown; }; type OnMessageEventHandler = (message: ProviderMessage) => void; type EIP1193OnEventHandler = OnConnectEventHandler | OnDisconnectEventHandler | OnChainChangedEventHandler | OnAccountsChangedEventHandler | OnMessageEventHandler; interface EIP1193Provider { rpcTimeoutDuration?: number; request: (request: { method: string; params?: Array<any> | undefined; }) => Promise<any>; on: (eventName: string, listener: EIP1193OnEventHandler) => any; removeListener: (eventName: string | symbol, listener: (...args: any[]) => void) => any; } interface RequestArguments { readonly method: string; readonly params?: readonly unknown[] | object | any; } declare global { interface Window { ethereum?: any; } } /** * @hidden * * The PrivyProxyProvider adds a middleware layer on top of the underlying wallet provider. * */ declare class PrivyProxyProvider implements EIP1193Provider { rpcTimeoutDuration: number; walletProvider?: EIP1193Provider; private _subscriptions; constructor(walletProvider?: EIP1193Provider, rpcTimeoutDuration?: number); on(eventName: string, listener: (...args: any[]) => void): any; request(request: { method: string; params?: any[] | undefined; }): Promise<any>; removeListener: (eventName: string | symbol, listener: (...args: any[]) => void) => any; walletTimeout: (error?: WalletTimeoutError, timeoutMs?: number) => Promise<string[]>; setWalletProvider: (provider: EIP1193Provider) => void; } type BaseAccountSdkCreateParams = Parameters<typeof createBaseAccountSDK>[0]; type BaseAccountSdkType = ReturnType<typeof createBaseAccountSDK>; type SetBaseAccountSdkType = (sdk: BaseAccountSdkType | undefined) => void; /** * Type of all Solana chains supported by Privy. */ type SolanaChain = (typeof SOLANA_CHAINS)[number]; /** * Helper type for defining a Standard Wallet with a union of Solana features. */ type SolanaStandardWallet = WalletWithFeatures<{ 'standard:connect'?: StandardConnectFeature['standard:connect']; 'standard:disconnect'?: StandardDisconnectFeature['standard:disconnect']; 'standard:events'?: StandardEventsFeature['standard:events']; 'solana:signMessage'?: SolanaSignMessageFeature['solana:signMessage']; 'solana:signTransaction'?: SolanaSignTransactionFeature['solana:signTransaction']; 'solana:signAndSendTransaction'?: SolanaSignAndSendTransactionFeature['solana:signAndSendTransaction']; 'solana:signIn'?: SolanaSignInFeature['solana:signIn']; }>; /** * Represents a connection with a single Solana wallet provider. Manages wallet state * including ongoing connection status, and exposes methods for connecting and disconnecting. */ declare class SolanaWalletConnector extends WalletConnector { chainType: "solana"; connectorType: string; wallets: BaseConnectedSolanaWallet[]; private _wallet; private autoConnectEnabled; private _unsubscribeListeners; constructor(wallet: Wallet$1, autoConnectEnabled: boolean); get isInstalled(): boolean; get wallet(): SolanaStandardWallet; /** * Builds a connected wallet object to be exposed to the developer. This object * contains the address and a few helper methods. * * Provider methods share the PrivyProxyProvider instance. This means that multiple * wallets may share the same provider if one wallet was disconnected and another * wallet was connected. * * A wallet is considered connected if it is present in the wallets array and is * in a connected state. * * @hidden */ buildConnectedWallet(): BaseConnectedSolanaWallet[]; /** * @hidden */ syncAccounts(): Promise<void>; /** * @hidden */ get walletBranding(): WalletBranding; /** * @hidden */ initialize(): Promise<void>; /** * @hidden */ connect(options: { showPrompt: boolean; }): Promise<BaseConnectedWallet | null>; /** * @hidden */ disconnect: () => Promise<void>; /** * @hidden */ promptConnection: () => Promise<void>; protected onChange: () => void; /** * Get the most recently connected wallet. * * @hidden */ getConnectedWallet(): Promise<BaseConnectedSolanaWallet | null>; /** * We depend on the adapter to manage the connection state. We consider a wallet * connected if the adapter is connected and its readyState is 'Installed'. * * @hidden */ isConnected(): Promise<boolean>; /** * @hidden */ subscribeListeners(): void; /** * @hidden */ unsubscribeListeners(): void; private shouldAttemptAutoConnect; } interface SolanaWalletConnectorsOptions { shouldAutoConnect?: boolean; } /** * Plugin object to add solana support to the Privy SDK */ type SolanaWalletConnectorsConfig = { /** * Creates listeners for when solana wallets are registered or unregistered */ onMount: () => void; /** * Remove listener registered by `onMount` */ onUnmount: () => void; /** * Get all Wallets that have been registered, converted to `SolanaWalletConnectors`. */ get: () => SolanaWalletConnector[]; }; /** * Wraps the wallet detection logic found in `@solana/wallet-standard-wallet-adapter-base` * and `@wallet-standard-app`. Returns a `SolanaWalletConnectors` object to be used with the `PrivyProvider`. * * @param {SolanaWalletConnectorsOptions} args Configuration object * @param {boolean} args.shouldAutoConnect Whether to automatically connect to the wallet. * Defaults to `true` and should not prompt the user loudly for connection. However, some legacy * adapters may still auto-connect loudly, so this flag can be used to disable that behavior. */ declare const toSolanaWalletConnectors: (args?: SolanaWalletConnectorsOptions) => SolanaWalletConnectorsConfig; /** * Accepted payment methods for the MoonPay fiat on-ramp. */ type MoonpayPaymentMethod = 'ach_bank_transfer' | 'credit_debit_card' | 'gbp_bank_transfer' | 'gbp_open_banking_payment' | 'mobile_wallet' | 'sepa_bank_transfer' | 'sepa_open_banking_payment' | 'pix_instant_payment' | 'yellow_card_bank_transfer'; type MoonpayUiConfig = { accentColor?: string; theme?: 'light' | 'dark'; }; /** * Cryptocurrency codes for the MoonPay fiat on-ramp. These codes * follow the format {TOKEN_NAME}_{NETWORK_NAME}. */ type MoonpayCurrencyCode = 'AVAX_CCHAIN' | 'CELO_CELO' | 'CUSD_CELO' | 'DAI_ETHEREUM' | 'ETH_ETHEREUM' | 'ETH_ARBITRUM' | 'ETH_POLYGON' | 'ETH_BASE' | 'FIL_FVM' | 'MATIC_ETHEREUM' | 'MATIC_POLYGON' | 'POL_POLYGON' | 'POL_ETHEREUM' | 'USDC_ETHEREUM' | 'USDC_ARBITRUM' | 'USDC_OPTIMISM' | 'USDC_POLYGON' | 'USDC_BASE' | 'USDC_CCHAIN' | 'USDT_ETHEREUM' | 'USDT_POLYGON' | 'WETH_POLYGON' | 'WBTC_ETHEREUM' | 'BNB_BNB' | 'BNB_BSC' | 'SOL' | 'USDC_SOL'; /** * Configuration parameter for the MoonPay fiat on-ramp. */ type MoonpayConfig = { currencyCode?: MoonpayCurrencyCode; quoteCurrencyAmount?: number; paymentMethod?: MoonpayPaymentMethod; uiConfig?: MoonpayUiConfig; }; type MoonpaySignRequest = { address: string; config: MoonpayConfig; useSandbox: boolean; }; type MoonpaySignResponse = { signedUrl: string; externalTransactionId: string; }; declare const DEFAULT_BICONOMY_PAYMASTER_CONTEXT: { mode: string; calculateGasLimits: boolean; expiryDuration: number; sponsorshipInfo: { webhookData: {}; smartAccountInfo: { name: string; version: string; }; }; }; type BiconomyPaymasterContext = typeof DEFAULT_BICONOMY_PAYMASTER_CONTEXT; type AlchemyPaymasterContextClient = { policyId: string; }; type CustomMetadataType = User$1['custom_metadata']; declare const SUPPORTED_RECOVERY_PROVIDERS: readonly ["google-drive", "icloud"]; declare const SUPPORTED_MFA_METHODS: readonly ["sms", "totp", "passkey"]; type MfaMethod = (typeof SUPPORTED_MFA_METHODS)[number]; type MfaSubmitArgs = { mfaMethod: MfaMethod; mfaCode: string | PasskeyAuthenticateRequestBody['authenticator_response']; relyingParty: string; }; type EntropyIdVerifier = 'ethereum-address-verifier' | 'solana-address-verifier'; /** * Supported OAuth providers for the recovery flow. Can be `'google-drive'` */ type RecoveryProviderType = (typeof SUPPORTED_RECOVERY_PROVIDERS)[number]; type LoginMethod = 'email' | 'sms' | 'siwe' | 'siws' | 'farcaster' | OAuthProviderID | 'passkey' | 'telegram' | 'custom' | 'guest'; type LoginWithCode = { /** * One-time password _([OTP](https://en.wikipedia.org/wiki/One-time_password))_ that was sent to user during first login step */ code: string; }; declare const EMBEDDED_WALLET_CLIENT_TYPES: readonly ["privy"]; type EmbeddedWalletClientType = (typeof EMBEDDED_WALLET_CLIENT_TYPES)[number]; declare const INJECTED_WALLET_CLIENT_TYPES: readonly ["metamask", "phantom", "brave_wallet", "rainbow", "uniswap_wallet_extension", "uniswap_extension", "rabby_wallet", "bybit_wallet", "ronin_wallet", "haha_wallet", "crypto.com_wallet_extension", "crypto.com_onchain", "binance", "bitget_wallet"]; type InjectedWalletClientType = (typeof INJECTED_WALLET_CLIENT_TYPES)[number]; declare const COINBASE_WALLET_CLIENT_TYPES: readonly ["coinbase_wallet", "coinbase_smart_wallet", "base_account"]; type CoinbaseWalletClientType = (typeof COINBASE_WALLET_CLIENT_TYPES)[number]; type WalletConnectWalletClientType = (typeof WALLET_CONNECT_WALLET_CLIENT_TYPES)[number]; declare const UNKNOWN_WALLET_CLIENT_TYPES: readonly ["unknown"]; type UnknownWalletClientType = (typeof UNKNOWN_WALLET_CLIENT_TYPES)[number]; declare const SOLANA_WALLET_CLIENT_TYPES: readonly ["phantom", "solflare", "glow", "backpack", "jupiter", "mobile_wallet_adapter"]; type SolanaWalletClientType = (typeof SOLANA_WALLET_CLIENT_TYPES)[number]; type WalletClientType = InjectedWalletClientType | CoinbaseWalletClientType | WalletConnectWalletClientType | EmbeddedWalletClientType | UnknownWalletClientType | SolanaWalletClientType; declare const SUPPORTED_CONNECTOR_TYPES: string[]; type ConnectorType = (typeof SUPPORTED_CONNECTOR_TYPES)[number]; /** * Wallet metadata currently for internal use only */ type WalletBranding = { name: string; id: string; icon?: string | EmbeddedSVG; }; type LinkedAccountType = 'wallet' | 'smart_wallet' | 'email' | 'phone' | 'google_oauth' | 'twitter_oauth' | 'discord_oauth' | 'github_oauth' | 'spotify_oauth' | 'instagram_oauth' | 'tiktok_oauth' | 'line_oauth' | 'twitch_oauth' | 'linkedin_oauth' | 'apple_oauth' | 'custom_auth' | 'farcaster' | 'passkey' | 'telegram' | 'cross_app' | 'authorization_key' | CustomOAuthProviderID | 'guest'; /** @ignore */ interface LinkMetadata { /** Account type, most commonly useful when filtering through linkedAccounts */ type: LinkedAccountType; /** Datetime when this account was linked to the user. */ firstVerifiedAt: Date | null; /** Datetime when this account was most recently used as a login/link method by the user. */ latestVerifiedAt: Date | null; } /** * Config for preferred credit card provider. We will default to using this method first if available. */ type PreferredCardProvider = 'coinbase' | 'moonpay'; /** * Configuration for the funding flow UIs. */ type FundingUiConfig = { receiveFundsTitle?: string; receiveFundsSubtitle?: string; landing?: { title?: string; }; }; /** * Configuration for Solana funding */ type SolanaFundingConfig = { /** The chain used for connections */ chain?: SolanaChain; /** The default amount in SOL */ amount?: string; /** The default funding method */ defaultFundingMethod?: DefaultFundingMethod; card?: { /** The preferred card provider for funding */ preferredProvider?: PreferredCardProvider; }; /** Customization for the funding UIs */ uiConfig?: FundingUiConfig; /** The asset to fund with */ asset?: 'native-currency' | 'USDC'; }; /** * Configuration for native funding amount. */ type NativeFundingConfig = { chain?: ChainLikeWithId; amount?: string; defaultFundingMethod?: DefaultFundingMethod; card?: { /** The preferred card onramp for funding */ preferredProvider?: PreferredCardProvider; }; /** Customization for the funding UIs */ uiConfig?: FundingUiConfig; } | { chain?: ChainLikeWithId; amount: string; asset: { erc20: Hex; } | 'USDC' | 'native-currency'; defaultFundingMethod?: DefaultFundingMethod; card?: { /** The preferred card onramp for funding */ preferredProvider?: PreferredCardProvider; }; /** Customization for the funding UIs */ uiConfig?: FundingUiConfig; }; /** * Optional configuration parameter for the fiat on-ramp. */ type FundWalletConfig = NativeFundingConfig; /** * Status of a funding transaction */ type FundingStatus = 'completed' | 'cancelled'; /** * Result returned when fundWallet() promise resolves */ interface FundingResult { /** * Status of the funding transaction */ status: FundingStatus; /** * Wallet address that was funded */ address: string; /** * Method used to fund the wallet */ fundingMethod: FundingMethod | undefined; /** * Transaction hash (if available from on-chain transfer or fiat provider) */ transactionHash?: string; /** * Amount transferred */ amount?: string; /** * Asset type transferred (e.g., 'Ether', 'USDC') */ assetType?: string; /** * Additional provider-specific metadata */ metadata?: { /** Type of wallet used (e.g., 'metamask', 'rainbow', 'phantom') */ walletClientType?: string; }; } /** * Possible methods of user-driven recovery. * This is set, per app, on the server. */ type UserRecoveryMethod = 'user-passcode' | RecoveryProviderType; /** * Object representation of a user's wallet. */ interface Wallet { /** The server wallet ID of the wallet. Null if the wallet is not delegated. Only applies to embedded wallets (`walletClientType === 'privy'` or `walletClientType === 'privy-v2'`). */ id?: string | null; /** The wallet address. */ address: string; /** * Chain type of the wallet address. */ chainType: WalletChainType; /** * The wallet client used for this wallet during the most recent verification. * * If the value is `privy`, then this is a privy embedded wallet. * * Other values include but are not limited to `metamask`, `rainbow`, `coinbase_wallet`, etc. */ walletClientType?: string; /** * The connector type used for this wallet during the most recent verification. * * This includes but is not limited to `injected`, `wallet_connect`, `coinbase_wallet`, `embedded`. */ connectorType?: string; /** * If this is a 'privy' embedded wallet, stores the recovery method: * * 1. 'privy': privy escrow of the recovery material * 2. 'user-passcode': recovery protected by user-input passcode */ recoveryMethod?: RecoveryMethod; /** Whether the wallet is imported. Only applies to embedded wallets (`walletClientType === 'privy'` or `walletClientType === 'privy-v2'`). */ imported: boolean; /** Whether the wallet is delegated. Only applies to embedded wallets (`walletClientType === 'privy'` or `walletClientType === 'privy-v2'`). */ delegated: boolean; /** HD index for the wallet. Only applies to embedded wallets (`walletClientType === 'privy'` or `walletClientType === 'privy-v2'`). */ walletIndex: number | null; /** Public key for the wallet. Only applies to tier 2 chains */ publicKey?: string; } /** * * Object representation of a base connected wallet from a wallet connector. */ interface BaseConnectedSolanaWallet extends BaseConnectedWallet { type: 'solana'; provider: ConnectedStandardSolanaWallet; } /** * Union type of all possible base connected wallets. */ type BaseConnectedWalletType = BaseConnectedEthereumWallet | BaseConnectedSolanaWallet; /** * Object representation of metadata reported by a connected wallet from a wallet connector */ interface ConnectedWalletMetadata { /** The wallet name (e.g. MetaMask). */ name: string; /** The wallet RDNS, falls back to the wallet name if none is available. */ id: string; /** The wallet logo */ icon?: string; } /** * Object representation of a base connected wallet from a wallet connector. */ interface BaseConnectedWallet { type: 'ethereum' | 'solana'; /** The wallet address. */ address: string; /** The first time this wallet was connected without break. */ connectedAt: number; /** * The wallet client where this key-pair is stored. * e.g. metamask, rainbow, coinbase_wallet, etc. */ walletClientType: WalletClientType; /** * The connector used to initiate the connection with the wallet client. * e.g. injected, wallet_connect, coinbase_wallet, etc. */ connectorType: ConnectorType; /** Whether the wallet is imported. */ imported: boolean; /** * Metadata for the wallet. */ meta: ConnectedWalletMetadata; /** Returns true if the wallet is connected, false otherwise */ isConnected: () => Promise<boolean>; /** * @experimental **Experimental**: This property is subject to change at any time. * * Not all wallet clients support programmatic disconnects (e.g. MetaMask, Phantom). * In kind, if the wallet's client does not support programmatic disconnects, * this method will no-op. */ disconnect: () => void; } /** * Object representation of a base connected Ethereum wallet from a wallet connector. */ interface BaseConnectedEthereumWallet extends BaseConnectedWallet { type: 'ethereum'; /** The current chain ID with CAIP-2 formatting. */ chainId: string; /** * Switch the network chain to a specified ID. * Note: The chainId must be a supported network: https://docs.privy.io/guide/frontend/embedded/networks * Note: This will not update any existing provider instances, re-request `wallet.getEthereumProvider` (e.g.) * to get a provider with the updated chainId. * * @param targetChainId The specified chain ID to switch to, as a number or 0x prefixed string. * @returns void */ switchChain: (targetChainId: `0x${string}` | number) => Promise<void>; /** Helper methods to build providers for interfacing with this wallet. */ getEthereumProvider: () => Promise<EIP1193Provider>; /** * Perform personal_sign with the user's wallet. * * @param {string} message The message to sign. * @returns {string} The resulting signature. */ sign: (message: string) => Promise<string>; } interface PrivyConnectedWallet { /** True if this wallet is linked to the authenticated user. False if it is not yet linked or * the user has not yet authenticated. */ linked: boolean; /** Login with this wallet or link this wallet to the authenticated user. * * Throws a PrivyClientError if the wallet is not connected. */ loginOrLink: () => Promise<void>; /** Unlink this wallet to the authenticated user. Throws a PrivyClientError if the user is not * authenticated. */ unlink: () => Promise<void>; /** The HD wallet index */ walletIndex?: number; } /** * Object representation of a connected wallet, with additional Privy flows */ interface ConnectedWallet extends BaseConnectedEthereumWallet, PrivyConnectedWallet { /** * Prompt the user to go through the funding flow and for the connected wallet. * * This will open the modal with a prompt for the user to select a funding method (if multiple are enabled). * * Once the user continues to the funding flow, Privy will display the funding status screen, and wait * for the transaction to complete. * * Note: Even after a successful funding, funds can take a few minutes to arrive in the user's wallet. * * Privy currently supports funding via external wallets and Moonpay. * * @param {FundWalletConfig} fundWalletConfig Funding configuration to specify chain and funding amount (if enabled) * **/ fund: (fundWalletConfig?: FundWalletConfig) => Promise<void>; } /** * Object representation of a smart wallet. */ interface SmartWallet { /** The wallet address. */ address: string; /** The provider of the smart wallet. */ smartWalletType: SmartWalletType; /** The version of the smart wallet. */ smartWalletVersion?: string; } /** Object representation of a user's email. */ interface Email { /** The email address. */ address: string; } /** Object representation of a user's phone number. */ interface Phone { /** The phone number. */ number: string; } /** Object representation of a user's Google account. */ interface Google { /** The `sub` claim from the Google-issued JWT for this account. */ subject: string; /** The email associated with the Google account. */ email: string; /** The name associated with the Google account. */ name: string | null; } /** Object representation of a user's Twitter account. */ interface Twitter { /** The `sub` claim from the Twitter-issued JWT for this account. */ subject: string; /** The username associated with the Twitter account. */ username: string | null; /** The name associated with the Twitter account. */ name: string | null; /** The profile picture URL associated with the Twitter account. * Note that the Twitter image URL returned is appended with `_normal` * to return a 48x48px image. In order to retrieve the original-sized image, * remove the `_normal` from the URL as specified in the Twitter API docs: * https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/user-profile-images-and-banners */ profilePictureUrl: string | null; } /** Object representation of a user's Discord account. */ interface Discord { /** The `sub` claim from the Discord-issued JWT for this account. */ subject: string; /** The username associated with the Discord account. */ username: string | null; /** The email associated with the Discord account. */ email: string | null; } /** Object representation of a user's Github account. */ interface Github { /** The `sub` claim from the Github-issued JWT for this account. */ subject: string; /** The username associated with the Github account. */ username: string | null; /** The name associated with the Github account. */ name: string | null; /** The email associated with the Github account. */ email: string | null; } /** Object representation of a user's Spotify account. */ interface Spotify { /** The user id associated with the Spotify account. */ subject: string; /** The email associated with the Spotify account. */ email: string | null; /** The display name associated with the Spotify account. */ name: string | null; } /** Object representation of a user's Instagram account. */ interface Instagram { /** The user id associated with the Instagram account. */ subject: string; /** The username associated with the Instagram account. */ username: string | null; } /** Object representation of a user's Tiktok account. */ interface Tiktok { /** The `sub` claim from the Tiktok-issued JWT for this account. */ subject: string; /** The username associated with the Tiktok account. */ username: string | null; /** The display name associated with the Tiktok account. */ name: string | null; } /** Object representation of a user's Line account. */ interface Line { /** The `sub` claim from the Line-issued JWT for this account. */ subject: string; /** The name associated with the Line account. */ name: string | null; /** The email associated with the Line account. */ email: string | null; /** The profile image URL associated with the Line account. */ profilePictureUrl: string | null; } /** Object representation of a user's Twitch account. */ interface Twitch { /** The unique identifier for the Twitch account. */ subject: string; /** The username associated with the Twitch account. */ username: string | null; } /** Object representation of a user's LinkedIn account. */ interface LinkedIn { /** The `sub` claim from the LinkedIn-issued JWT for this account. */ subject: string; /** The name associated with the LinkedIn account. */ name: string | null; /** The email associated with the LinkedIn account. */ email: string | null; /** The vanityName/profile URL associated with the LinkedIn account. */ vanityName: string | null; } /** Object representation of a user's Apple account. */ interface Apple { /** The `sub` claim from the Apple-issued JWT for this account. */ subject: string; /** The email associated with the Apple account. */ email: string; } /** Object representation of a user's Custom OAuth Account. */ interface CustomOAuth { /** The `sub` claim from the Custom OAuth-issued JWT for this account. */ subject: string; /** The name associated with the Custom OAuth account. */ name: string | null; /** The username associated with the Custom OAuth account. */ username: string | null; /** The email associated with the Custom OAuth account. */ email: string | null; /** The profile picture URL associated with the Custom OAuth account. */ profilePictureUrl: string | null; } interface CustomJwtAccount { /** The user ID given by the custom auth provider */ customUserId: string; } interface Farcaster { /** The Farcaster on-chain FID */ fid: number | null; /** The Farcaster ethereum address that owns the FID */ ownerAddress: string; /** The Farcaster protocol username */ username: string | null; /** The Farcaster protocol display name */ displayName: string | null; /** The Farcaster protocol bio */ bio: string | null; /** The Farcaster protocol profile picture */ pfp: string | null; /** The Farcaster protocol profile url */ url: string | null; /** The public key of the signer, if set. This is not guaranteed to be valid, as the user can revoke the key at any time */ signerPublicKey: string | null; } interface Telegram { /** The user ID that owns this Telegram account. */ telegramUserId: string; /** The first name of the user . */ firstName: string | null; /** The last name of the user . */ lastName: string | null; /** The username associated with the Telegram account. */ username: string | null; /** The url of the user's profile picture. */ photoUrl: string | null; } interface Passkey { /** The passkey credential ID */ credentialId: string; /** The passkey public key (base64 encoded) */ publicKey?: string; /** Whether or not this passkey can be used for MFA */ enrolledInMfa: boolean; /** The type of authenticator holding the passkey */ authenticatorName?: string; /** Metadata about the device that registered the passkey */ createdWithDevice?: string; /** Metadata about the OS that registered the passkey */ createdWithOs?: string; /** Metadata about the browser that registered the passkey */ createdWithBrowser?: string; } /** Metadata about the provider app for a cross-app account */ interface ProviderAppMetadata { /** Privy app ID for the provider app. */ id: string; /** Name for the provider app. */ name?: string; /** Logo URL for the provider app. */ logoUrl?: string; } interface CrossAppAccount { /** The user's embedded wallet address(es) from the provider app */ embeddedWallets: { address: string; }[]; smartWallets: { address: string; }[]; providerApp: ProviderAppMetadata; subject: string; } /** Object representation of a user's email, with additional metadata for advanced use cases. */ interface EmailWithMetadata extends LinkMetadata, Email { /** Denotes that this is an email account. */ type: 'email'; } /** Object representation of a user's phone number, with additional metadata for advanced use cases. */ interface PhoneWithMetadata extends LinkMetadata, Phone { /** Denotes that this is a phone account. */ type: 'phone'; } /** Object representation of a user's wallet, with additional metadata for advanced use cases. */ interface WalletWithMetadata extends LinkMetadata, Wallet { /** Denotes that this is a wallet account. */ type: 'wallet'; } interface SmartWalletWithMetadata extends LinkMetadata, SmartWallet { /** Denotes that this is a smart wallet account. */ type: 'smart_wallet'; } /** Object representation of an HD embedded wallet with a defined `walletIndex` */ type HDWalletWithMetadata = WalletWithMetadata & { walletIndex: number; }; /** Object representation of a user's Google Account, with additional metadata for advanced use cases. */ interface GoogleOAuthWithMetadata extends LinkMetadata, Google { /** Denotes that this is a Google account. */ type: 'google_oauth'; } /** Object representation of a user's Twitter Account, with additional metadata for advanced use cases. */ interface TwitterOAuthWithMetadata extends LinkMetadata, Twitter { /** Denotes that this is a Twitter account. */ type: 'twitter_oauth'; } /** Object representation of a user's Discord Account, with additional metadata for advanced use cases. */ interface DiscordOAuthWithMetadata extends LinkMetadata, Discord { /** Denotes that this is a Discord account. */ type: 'discord_oauth'; } /** Object representation of a user's Github Account, with additional metadata for advanced use cases. */ interface GithubOAuthWithMetadata extends LinkMetadata, Github { /** Denotes that this is a Github account. */ type: 'github_oauth'; } /** Object representation of a user's Spotify Account, with additional metadata for advanced use cases. */ interface SpotifyOAuthWithMetadata extends LinkMetadata, Spotify { /** Denotes that this is a Spotify account. */ type: 'spotify_oauth'; } /** Object representation of a user's Instagram Account, with additional metadata for advanced use cases. */ interface InstagramOAuthWithMetadata extends LinkMetadata, Instagram { /** Denotes that this is a Instagram account. */ type: 'instagram_oauth'; } /** Object representation of a user's Tiktok Account, with additional metadata for advanced use cases. */ interface TiktokOAuthWithMetadata extends LinkMetadata, Tiktok { /** Denotes that this is a Tiktok account. */ type: 'tiktok_oauth'; } /** Object representation of a user's Line Account, with additional metadata for advanced use cases. */ interface LineOAuthWithMetadata extends LinkMetadata, Line { /** Denotes that this is a Line account. */ type: 'line_oauth'; } /** Object representation of a user's Twitch Account, with additional metadata for advanced use cases. */ interface TwitchOAuthWithMetadata extends LinkMetadata, Twitch { /** Denotes that this is a Twitch account. */ type: 'twitch_oauth'; } /** Object representation of a user's LinkedIn Account, with additional metadata for advanced use cases. */ interface LinkedInOAuthWithMetadata extends LinkMetadata, LinkedIn { /** Denotes that this is a LinkedIn account. */ type: 'linkedin_oauth'; } /** Object representation of a user's Apple Account, with additional metadata for advanced use cases. */ interface AppleOAuthWithMetadata extends LinkMetadata, Apple { /** Denotes that this is a Apple account. */ type: 'apple_oauth'; } /** Object representation of a user's Custom OAuth Account, with additional metadata for advanced use cases. */ interface CustomOAuthWithMetadata extends LinkMetadata, CustomOAuth { /** Denotes that this is a Custom OAuth account. */ type: CustomOAuthProviderID; } /** Object representation of a user's Custom JWT Account, with additional metadata for advanced use cases. */ interface CustomJwtAccountWithMetadata extends LinkMetadata, CustomJwtAccount { /** Denotes that this is an custom account. */ type: 'custom_auth'; } /** Object representation of a user's Farcaster Account, with additional metadata for advanced use cases. */ interface FarcasterWithMetadata extends LinkMetadata, Farcaster { /** Denotes that this is a Farcaster account. */ type: 'farcaster'; } /** Object representation of a user's Passkey Account, with additional metadata for advanced use cases. */ interface PasskeyWithMetadata extends LinkMetadata, Passkey { /** Denotes that this is a Passkey account. */ type: 'passkey'; } /** Object representation of a user's Telegram Account, with additional metadata for advanced use cases. */ interface TelegramWithMetadata extends LinkMetadata, Telegram { /** Denotes that this is a Telegram account. */ type: 'telegram'; } /** Object representation of a user's cross-app account, with additional metadata for advanced use cases. */ interface CrossAppAccountWithMetadata extends LinkMetadata, CrossAppAccount { /** Denotes that this is a cross-app account */ type: 'cross_app'; } /** * Object representation of a user's linked accounts */ type LinkedAccountWithMetadata = WalletWithMetadata | SmartWalletWithMetadata | EmailWithMetadata | PhoneWithMetadata | GoogleOAuthWithMetadata | TwitterOAuthWithMetadata | DiscordOAuthWithMetadata | GithubOAuthWithMetadata | SpotifyOAuthWithMetadata | InstagramOAuthWithMetadata | TiktokOAuthWithMetadata | LineOAuthWithMetadata | TwitchOAuthWithMetadata | LinkedInOAuthWithMetadata | AppleOAuthWithMetadata | CustomOAuthWithMetadata | CustomJwtAccountWithMetadata | FarcasterWithMetadata | PasskeyWithMetadata | TelegramWithMetadata | CrossAppAccountWithMetadata; interface User { /** The Privy-issued DID for the user. If you need to store additional information * about a user, you can use this DID to reference them. */ id: string; /** The datetime of when the user was created. */ createdAt: Date; /** The user's email address, if they have linked one. It cannot be linked to another user. */ email?: Email; /** The user's phone number, if they have linked one. It cannot be linked to another user. */ phone?: Phone; /** The user's first verified wallet, if they have linked at least one wallet. * It cannot be linked to another user. **/ wallet?: Wallet; /** * The user's smart wallet, if they have set up through the Privy Smart Wallet SDK. */ smartWallet?: SmartWallet; /** The user's Google account, if they have linked one. It cannot be linked to another user. */ google?: Google; /** The user's Twitter account, if they have linked one. It cannot be linked to another user. */ twitter?: Twitter; /** The user's Discord account, if they have linked one. It cannot be linked to another user. */ discord?: Discord; /** The user's Github account, if they have linked one. It cannot be linked to another user. */ github?: Github; /** The user's Spotify account, if they have linked one. It cannot be linked to another user. */ spotify?: Spotify; /** The user's Instagram account, if they have linked one. It cannot be linked to another user. */ instagram?: Instagram; /** The user's Tiktok account, if they have linked one. It cannot be linked to another user. */ tiktok?: Tiktok; /** The user's Line account, if they have linked one. It cannot be linked to another user. */ line?: Line; /** The user's Twitch account, if they have linked one. It cannot be linked to another user. */ twitch?: Twitch; /** The user's LinkedIn account, if they have linked one. It cannot be linked to another user. */ linkedin?: LinkedIn; /** The user's Apple account, if they have linked one. It cannot be linked to another user. */ apple?: Apple; /** The user's Farcaster account, if they have linked one. It cannot be linked to another user. */ farcaster?: Farcaster; /** The user's Telegram account, if they have linked one. It cannot be linked to another user. */ telegram?: Telegram; /** The list of accounts associated with this user. Each account contains additional metadata * that may be helpful for advanced use cases. */ linkedAccounts: Array<LinkedAccountWithMetadata>; /** The list of MFA Methods associated with this user. */ mfaM