# Adding the SDK If you want to skip the step by step guide, you can refer to one of [the example apps](/example-apps#react-18) or [the quickstart](/quickstart). ## Installing the SDK To get started, you need to install the SDK. You can do this by running the following command: ```bash npm npm install @dynamic-labs/sdk-react-core ``` ```bash yarn yarn add @dynamic-labs/sdk-react-core ``` {" "} The SDK uses Viem by default. If you need Ethers, please complete this guide first, and you'll find a link to the Ethers guide at the bottom. ## Adding the context provider The miminum implementation involves wrapping your app with the [`DynamicContextProvider` component](/adding-dynamic/dynamic-context-provider). This provider allows your application to use Dynamic functionality. Make sure to replace `XXXXX` with your environment ID, found [here](https://app.dynamic.xyz/dashboard/developer/api). ```jsx import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core"; return ( ); ``` If you have any issues while implementing at this stage, check out [the React troubleshooting section](/troubleshooting/react). Now you have access to Dynamic inside your app, you can start using the SDK to enable signup/login, once you've enabled a chain! If you want to skip the step by step guide, you can refer to one of [the example apps](/example-apps#next-js). ## Installing the SDK To get started, you need to install the SDK. You can do this by running the following command: ```bash npm npm install @dynamic-labs/sdk-react-core ``` ```bash yarn yarn add @dynamic-labs/sdk-react-core ``` The SDK uses Viem by default. If you need Ethers, please complete this guide first, and you'll find a link to the Ethers guide at the bottom. ## Adding the context provider The miminum implementation involves installing the [`DynamicContextProvider` component](adding-dynamic/dynamic-context-provider) and wrapping your app with it. Because the components will need to be client side rendered, we recommend creating a new file called Dynamic.ts and exporting Dynamic from there: Make sure to replace `XXXXX` with your environment ID, found [here](https://app.dynamic.xyz/dashboard/developer/api). ```jsx // lib/dynamic.ts "use client"; export * from "@dynamic-labs/sdk-react-core"; ``` You can then import Dynamic from this file in your pages: ```jsx // app/layout.tsx import { DynamicContextProvider } from "../lib/dynamic"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); } ``` If you have any issues while implementing at this stage, check out [the NextJS troubleshooting section](troubleshooting/next). Now you have access to Dynamic inside your app, you can start using the SDK to enable signup/login, once you've enabled a chain! Click here to learn how to enable chains and wallets with the SDK # DynamicContextProvider props This is the main provider for the Dynamic SDK. It is used to initialize the SDK and pass in settings. Learn how to install the SDK and add the context provider [here](/adding-dynamic/adding-the-sdk). Below we provide the complete list of props that can be passed to the `DynamicContextProvider` component. It's a lot! Don't worry though, we reference each prop in the respective tutorials, so you'll learn about them in context as you complete different guides. ## Settings Passed in using the "settings" prop, available when you first initialize `DynamicContextProvider` in your App. | Method | Description | | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | accessDeniedMessagePrimary?: string; | Custom main error message used when a wallet attempts to authenticate via Dynamic and is rejected because it does not have access. Defaults to “Access denied” | | accessDeniedMessageSecondary?: string; | Custom secondary error message used when a wallet attempts to authenticate via Dynamic and is rejected because it does not have access. Defaults to “We couldn't find your wallet address on our access list of customers.” | | accessDeniedButton?: AccessDeniedCustomButton; | Custom secondary error button text and action when a wallet attempts to authenticate via Dynamic and is rejected because it does not have access. Defaults to "Try another method" and allow user to choose another login option. Please see: [AccessDeniedCustomButton](/react-sdk/objects/access-denied-custom-button) | | coinbaseWalletPreference?: 'all' \| 'smartWalletOnly' \| 'eoaOnly'; | Determines which connection options users will see. Defaults to all. Please see: [https://www.smartwallet.dev/sdk/makeWeb3Provider#options-optional](https://www.smartwallet.dev/sdk/makeWeb3Provider#options-optional) | | cssOverrides?: string \| JSX.Element; | Allows for custom CSS overrides via ShadowDom. Please see: [Custom CSS](/design-customizations/css/custom-css) | | debugError?: boolean; | When enabled, errors caught during the authentication step and their stack trace will be set in a state and displayed in the front end. | | deepLinkPreference?: 'native' \| 'universal'; | Used to control the type of deep link used when connecting a mobile wallet. Defaults to 'native'. This is useful for example if your app is running in a webview of a native mobile app, and you want to be able to link out to any wallet without having to modify your iOS build config. In this case, you can set this to 'universal'. | | displaySiweStatement?: boolean; | When enabled, this will show a message on terms of service and privacy policy in the signing message on the authentication step. | | enableVisitTrackingOnConnectOnly?: boolean; | When the Dynamic SDK is being used with auth mode = connect-only, we require this to be set to “true” to track visits of connected wallets in this environment. | | environmentId: string; | You will need to specify your app’s environment ID, which refers to a unique environment and its settings in Dynamic. To get your environment ID, go to [dashboard’s API tab](https://app.dynamic.xyz/dashboard/api) | | eventsCallbacks?: DynamicEventsCallbacks; | This prop allows custom event callbacks after important events during the authentication flows for Dynamic's React SDK. For more information, please see [the main SDK reference](/react-sdk) | | evmNetworks?: \[]EvmNetwork | An array of [EvmNetwork](/react-sdk/objects/evmNetwork), more details in [the custom networks guide](/chains/network-switching). | | initialAuthenticationMode?: AuthModeType; | Sets the initial SDK authentication mode to either connect-only or connect-and-sign. connect-only does not require users to authenticate to prove ownership of their wallet. connect-and-sign will require an additional step for users to prove ownership of their wallet. Defaults to connect-and-sign. See also the [setAuthMode](/react-sdk/hooks/usedynamiccontext) method, which allows you to toggle this after the app has loaded. | | logLevel?: keyof typeof LogLevel; | The log level to use for client side logging with our SDK. Defaults to WARN | | mobileExperience?: 'in-app-browser' \| 'redirect' | Available from SDK V1.1. Controls the mobile user experience of connecting to native app wallets. Defaults to 'in-app-browser', meaning that we will deep link into the native wallet's in-app browser. Set to 'redirect' for an experience where the user accepts prompts in the native wallet and is redirected back to the mobile browser. This is currently applicable to Phantom. | | networkValidationMode?: 'always' \| 'sign-in' \| 'never' | Note: Supported only in connect-only. Defines how the Dynamic SDK will enforce the wallet network.
- always - requires the wallet to be on an enabled network while connecting and while the session is active
- sign-in - will only enforce the network on connect
- never - completely turn off the network validation. Defaults to `sign-in`. | | newToWeb3WalletChainMap?: ChainToWalletMap; | When provided, this is used in the Get your first wallet view in the wallet list modal. This can be helpful to steer initial customers who do not have a wallet to download and use a specific chain and wallet. | | onboardingImageUrl?: string; | When provided, this image will be shown during the customer information capture step after a wallet successfully authenticates with Dynamic and the environment requires additional information from the user. | | policiesConsentInnerComponent?: ReactNode \| ReactNode\[]; | For environments with the username setting enabled, you will need to pass in a value for this prop to show a custom prompt or label for the policies contest checkboxes displayed during customer information capture after signing. | | privacyPolicyUrl?: string; | When provided, this will display a privacy policy URL on the signing step. This should be set to a URL of your organization’s privacy policy web page. | | recommendedWallets: [RecommendedWallet](/wallets/advanced-wallets/recommend-wallets#general-wallet-list)\[]; | Available from V1.2 only. An array of wallet keys that will be recommended to the user. See more in [our section on recommending wallets](/wallets/advanced-wallets/recommend-wallets). | | shadowDOMEnabled?: boolean; | Shadow DOM allows the SDK to look as intended wherever it is hosted and it plays nicely with your existing styling system. For more information, please see: [Custom CSS](/design-customizations/css/custom-css) | | siweStatement?: string; | When provided, this custom message will be shown on the message to sign for the wallet signing step. | | termsOfServiceUrl?: string; | When provided, this will display a terms of service URL on the signing step. This should be set to a URL of your organization’s terms of service web page. | | walletConnectors?: [walletConnector](/chains/enabling-chains)\[] | When provided, will enable whatever connectors you pass so that your end user can signup/login using those wallets. For the list of available connectors, see the walletConnectors section below. | | walletConnectorExtensions?: \[]WalletConnectorExtension | Currently only used to enable Ethers instead of Viem which is the default, for example see examples section below. For more info on Ethers instead of viem please [see here](/quickstart#step-4-stick-with-viem-or-switch-to-ethers) | | walletConnectPreferredChains | Relevant to Wallet Connect only, used to determine which chains to establish a connection with first. The value must be an array containing [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) chain ID's. The format for this is `{namespace-goes-here}:{reference-goes-here}`. Currently we only support Ethereum, so it will always be `eip155:{reference-goes-here}`. For example, Ethereum mainnet being \['eip155:1'] | | walletsFilter?: (options: WalletOption\[]) => [WalletOption](/react-sdk/objects/wallet-option)\[]; | When specified, this is a custom function that allows clients of Dynamic SDK to filter out wallet options based on a function on the wallet options. For example: walletsFilter: (wallets) => wallets.filter((w) => w\.key !== "walletx") will exclude walletx from showing up on the wallet list. | | bridgeChains?: [bridgeChains](/building-bridges/dynamic-bridge-widget) | (Only use with bridging) Which chains should be used for bridging. | | socialProvidersFilter?: (providers: SocialOAuthProvider\[]) => SocialOAuthProvider\[]; | When specified, this is a custom function that allows clients of Dynamic SDK using social auth to filter or modify the order of the social options displayed to the user. For example, we can only show github oauth option: socialProvidersFilter: (providers) => (\['github']). | | overrides: \{views: SdkView\[]} | Used only for passing in [Views](/react-sdk/objects/views) right now. You can find examples in the view page previously mentioned or a more complete example [here](/design-customizations/tutorials/login-views-guide). | | enableConnectOnlyFallback?: boolean | When `true`, enables the SDK to fallback to wallet connect-only auth mode if a connection to our servers is not possible. Available in version 1.1 and above. | # Using Ethers instead of Viem The SDK and above ships with Viem by default as it is much lighter than Ethers and is generally more performant. We have also made viem a peerDependency to avoid bundling it multiple times, as other other packages such as wagmi also need it. For the above reason, viem will be installed as a peerDependency when you install the SDK with npm, even if you want to use Ethers. If you are using yarn instead of npm, even if you want to use Ethers, you will need to install viem manually: ```bash yarn i viem ``` Dynamic only supports version v6+ of Ethers. In order to use it, simply import the ethers methods you need from `@dynamic-labs/ethers-v6` directly in the component where you are using them. ```bash npm i @dynamic-labs/ethers-v6 ``` ```jsx import { useDynamicContext } from '@dynamic-labs/sdk-react-core' import { getWeb3Provider,getSigner, } from '@dynamic-labs/ethers-v6' const { primaryWallet } = useDynamicContext() const provider = await getWeb3Provider(primaryWallet) const signer = await getSigner(primaryWallet) // do your thing ``` # Wagmi & Dynamic #### Installing packages First, you want to install the DynamicWagmiConnector package using `npm` or `yarn` ```shell npm npm install viem wagmi @tanstack/react-query @dynamic-labs/wagmi-connector @dynamic-labs/sdk-react-core @dynamic-labs/ethereum ``` ```shell yarn yarn add viem wagmi @tanstack/react-query @dynamic-labs/wagmi-connector @dynamic-labs/sdk-react-core @dynamic-labs/ethereum ``` ```shell pnpm pnpm add viem wagmi @tanstack/react-query @dynamic-labs/wagmi-connector @dynamic-labs/sdk-react-core @dynamic-labs/ethereum ``` #### Configure Wagmi and Dynamic Here's a full code snippet with all the setup code required. ```TypeScript import { DynamicContextProvider, DynamicWidget, } from '@dynamic-labs/sdk-react-core'; import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'; import { DynamicWagmiConnector } from '@dynamic-labs/wagmi-connector'; import { createConfig, WagmiProvider, useAccount, } from 'wagmi'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { http } from 'viem'; import { mainnet } from 'viem/chains'; const config = createConfig({ chains: [mainnet], multiInjectedProviderDiscovery: false, transports: { [mainnet.id]: http(), }, }); const queryClient = new QueryClient(); export default function App() { return ( ); } function AccountInfo() { const { address, isConnected, chain } = useAccount(); return (

wagmi connected: {isConnected ? 'true' : 'false'}

wagmi address: {address}

wagmi network: {chain?.id}

); }; ``` Two things to note here: 1. `multiInjectedProviderDiscovery` is set to `false` – this is because Dynamic implements the multi injected provider discovery protocol itself. If you'd like to keep this enabled on Wagmi, please do, but you might see some undefined behavior and we might not be able to debug. 2. While this example configures mainnet as the only chain, you can pass in all your supported chains to the `chains` array. For more info, see the "Chain Configuration" section below. Throughout your app, you can now use Wagmi hooks like `useAccount` and they will automatically sync to the wallet that you logged in with via Dynamic. Make sure to call `createConfig` at the top-level of your app. If you call it inside of a component, it will be called during each render, which can lead to unexpected behavior. #### Chain Configuration If you are upgrading from Dynamic + Wagmi v1, then this config will look new to you. Previously, Dynamic was automatically updating the Wagmi config with the chains that you configured in your Dynamic Dashboard. This behavior has changed in v2 to give you more control over your Wagmi config and for a simpler integration. What this means is that you will need to pass to Wagmi all of the chains you have configured with Dynamic. For example, if in Dynamic you have enabled Ethereum Mainnet, Optimism and Base, you will need to update your Wagmi config to look like this: ```TypeScript import { createConfig, WagmiProvider, } from 'wagmi'; import { http } from 'viem'; import { mainnet, optimism, base } from 'viem/chains'; const config = createConfig({ chains: [mainnet, optimism, base], multiInjectedProviderDiscovery: false, transports: { [mainnet.id]: http(), [optimism.id]: http(), [base.id]: http(), }, }); ``` ### Adding Custom Networks As you probably already know, you can add a custom EVM network through Dynamic using [the evmNetworks prop](/chains/evmNetwork). If you want to use these custom networks with Wagmi, you will need to declare it in your Wagmi config. You can use our util function called \[getOrMapViemChain] to convert the EVM network object to a Viem chain object. Here's an example of adding the Morph network to both Dynamic and to the Wagmi config: ```tsx import { createConfig, WagmiProvider, } from 'wagmi'; import { http } from 'viem'; import { getOrMapViemChain } from '@dynamic-labs/sdk-react-core'; const customEvmNetworks = [ { blockExplorerUrls: ["https://explorer-holesky.morphl2.io/"], chainId: 2810, name: "Morph", rpcUrls: ["https://rpc-quicknode-holesky.morphl2.io"], iconUrls: ["https://avatars.githubusercontent.com/u/132543920?v=4"], nativeCurrency: { name: "Ethereum", symbol: "ETH", decimals: 18, }, networkId: 2810, }, ] export const wagmiConfig = createConfig({ chains: [ mainnet, ...customEvmNetworks.map(getOrMapViemChain), ], client({ chain }) { return createClient({ chain, transport: http(), }); }, }); ``` ### Adding Private RPCs Note that if you are using [a private RPC in Dynamic](/chains/rpc-urls#dashboard-configuration), you will also need to declare that in your Wagmi config. Luckily this is as simple as passing it into your http transport in Wagmi: ```tsx import { createConfig, WagmiProvider, } from 'wagmi'; export const wagmiConfig = createConfig({ chains: [mainnet], multiInjectedProviderDiscovery: false, transports: { [mainnet.id]: http('your-private-rpc-url'), }, }); ``` ### Further Resources For docs on `createConfig`, see: [https://wagmi.sh/react/api/createConfig](https://wagmi.sh/react/api/createConfig) For more general information on what you can do with Wagmi, check out their getting started docs: [https://wagmi.sh/react/getting-started](https://wagmi.sh/react/getting-started) # Create new allowlist for a environment POST /environments/{environmentId}/allowlists # Delete an allowlist DELETE /allowlists/{allowlistId} # Delete an allowlist entry DELETE /allowlistEntries/{allowlistEntryId} # Disable the allow list PUT /allowlists/{allowlistId}/disable # Enable the allowlist PUT /allowlists/{allowlistId}/enable # Get all allowlists for a environment GET /environments/{environmentId}/allowlists # Get allowlist by id GET /allowlists/{allowlistId} # Get all entries for an allowlist GET /allowlists/{allowlistId}/entries # Create a new entry for an allowlist POST /allowlists/{allowlistId}/entries # Update the outcome, scope, or name of an allowlist entry by ID PUT /allowlists/{allowlistId} # getVisitAnalytics GET /environments/{environmentId}/analytics/visits Fetch visit analytics # Fetch visit analytics GET /environments/{environmentId}/analytics/wallets Fetch wallets breakdown # Disables the Sanctions API PUT /environments/{environmentId}/integrations/chainalysis/sanctions/disable # Enable the Sanctions API PUT /environments/{environmentId}/integrations/chainalysis/sanctions/enable # Find the Chainalysis configuration for an environment. GET /environments/{environmentId}/integrations/chainalysis # Get tokens for passed chainName. GET /chains/{chainName}/tokens # Create a new custom field for an environment POST /environments/{environmentId}/custom/fields # Delete a specific custom field by its ID DELETE /custom/fields/{customFieldId} # Retrieve a specific custom field by its ID GET /custom/fields/{customFieldId} # Get the custom fields for an environment GET /environments/{environmentId}/custom/fields # Update an existing custom field by its ID PUT /custom/fields/{customFieldId} # Deletes an environment by ID DELETE /environments/{environmentId} # Find an environment by ID GET /environments/{environmentId} # Get Live and Sandbox environments by projectId GET /projects/{projectId}/environments # Get keys for an environment given environmentId GET /environments/{environmentId}/keys # Get the unique number of visitors for an environment by environment ID GET /environments/{environmentId}/statistics/visitors # Updates the environment settings PUT /environments/{environmentId} # Get event types GET /eventTypes # Get environment events GET /environments/{environmentId}/events # Create a new export request for the project environment POST /environments/{environmentId}/exports # Download an export by ID GET /exports/{exportId}/download # Get the exports for an environment GET /environments/{environmentId}/exports # Get an export using the ID GET /exports/{exportId} # Check if the external provided JWT is valid for the specified environment POST /environments/{environmentId}/externalJwt/check # Creates a new gate for the project environment POST /environments/{environmentId}/gates # Delete a gate DELETE /gates/{gateId} # Disable the gate for the environment PUT /gates/{gateId}/disable # Enable the gate for the environment PUT /gates/{gateId}/enable # Get the gates for an environment GET /environments/{environmentId}/gates # Gets a gate GET /gates/{gateId} # Updates a gate PUT /gates/{gateId} # Creates an invite to the organization POST /organizations/{organizationId}/invites # Delete invite for user DELETE /invites/{inviteId} # Get all the user invites GET /invites # Fetches all the Invites the belong to the organization GET /organizations/{organizationId}/invites # Update invite for user (accept/reject) PUT /invites/{inviteId} # Delete user membership from being an admin of an organization DELETE /members/{memberId} # Get all users that are admins for an organization GET /organizations/{organizationId}/members # Get Membership Environment IDs GET /membershipEnvironmentIds Retrieve the list of project environments that the user is a member of. # Update a given members role PUT /members/{memberId} # Creates organization POST /organizations # Deletes an organization by ID DELETE /organizations/{organizationId} # Find the subscription of an organization using its ID GET /organizations/{organizationId}/billing/subscription # Find an organization by ID GET /organizations/{organizationId} # Fetches all the active organizations that the user has access to GET /organizations # Update an organization by ID PUT /organizations/{organizationId} # Upgrade organziation to advanced plan PUT /organizations/{organizationId}/billing/upgrade # Adds an allowed origin for this project environment POST /environments/{environmentId}/origins # Delete a origin by id DELETE /origins/{originId} # Get all the allowed origins for a project environment GET /environments/{environmentId}/origins # Creates a new project POST /organizations/{organizationId}/projects # Deletes a project by ID DELETE /projects/{projectId} # Find an project by ID GET /projects/{projectId} # Fetches all the active projects the belong to the organization GET /organizations/{organizationId}/projects # Update a project PUT /projects/{projectId} # Get a sdk view given a type and environment GET /environments/{environmentId}/sdkViews/{sdkViewType} # Get the sdk views for an environment GET /environments/{environmentId}/sdkViews # Updates the configs for the sdk view and project environment PUT /environments/{environmentId}/sdkViews/{sdkViewType} # Revoke a session PUT /sessions/{sessionId}/revoke # Creates a new provider for the project environment POST /environments/{environmentId}/settings/providers # Delete a provider by providerId DELETE /settings/providers/{providerId} # Disable the provider for the environment PUT /settings/providers/{providerId}/disable # Enable the provider for the environment PUT /settings/providers/{providerId}/enable # Get the URLs for the environment providers GET /environments/{environmentId}/settings/providers/urls # Get the providers for an environment GET /environments/{environmentId}/settings/providers # Gets a provider GET /settings/providers/{providerId} # Updates a provider PUT /settings/providers/{providerId} # Delete a token by token id DELETE /tokens/{tokenId} # Get all the tokens for a project environment (does not include the raw token) GET /environments/{environmentId}/tokens # Create a new API Token POST /environments/{environmentId}/tokens # Creates many new users POST /environments/{environmentId}/users/bulk # Creates a new user POST /environments/{environmentId}/users # Delete user DELETE /users/{userId} # Get all users for an environment GET /environments/{environmentId}/users # Get a user by Id GET /users/{userId} # Get the access token for a user OAuth account GET /oauthAccounts/{oauthAccountId}/accessToken # Revoke sessions by user ID POST /users/{userId}/sessions/revoke # Update a user PUT /users/{userId} # Creates a new embedded wallet for a user given an identifier POST /environments/{environmentId}/embeddedWallets Creates a new embedded wallet for a user given an email or userId. If an email is provided and it is not associated with an existing user this call will also create a new user. # Creates a new embedded wallet. This API is meant to be called from a frame server. POST /environments/{environmentId}/embeddedWallets/farcaster Creates a new embedded wallet. This API is meant to be called from a frame server. # Creates a new wallet for the user POST /users/{userId}/wallets Creates a new wallet for the user. Note that this API is not meant for creating embedded wallets. To create embedded wallets use the /embeddedWallets endpoint. # Delete wallet DELETE /wallets/{walletId} # Get a wallet using the ID GET /wallets/{walletId} # Get wallets by user GET /users/{userId}/wallets # Creates a new Webhooks for the project environment POST /environments/{environmentId}/webhooks # Delete the Webhook for an environment DELETE /environments/{environmentId}/webhooks/{webhookId} # Get the Webhook for an environment GET /environments/{environmentId}/webhooks/{webhookId} # Get the Messages for an webhook GET /environments/{environmentId}/webhooks/{webhookId}/messages # Get the Webhooks for an environment GET /environments/{environmentId}/webhooks # Redeliver message for an webhook POST /environments/{environmentId}/webhooks/{webhookId}/messages/{messageId}/redeliver # Update the Webhook for an environment PUT /environments/{environmentId}/webhooks/{webhookId} # Introduction ## Introduction Dynamic provides a robust API that allows developers to securely access their dashboard environment's data and programmatically update settings relevant to their Dynamic-powered application. ## Authentication All APIs in this section require a bearer token used to authenticate requests and make sure the caller is authorized to access the resources in the requests. Please follow these steps: #### Get an API token from Dashboard 1. Go to the your environment's dashboard [Developer Tab](https://app.dynamic.xyz/dashboard/developer/api) 2. In the "API Token" section, click on "Create Token" 3. Provide a name for the token. The best practice here would be to name the token after the system you intend to use this token with. A few examples: "Mycompany Admin", "Ben's personal token", or "background-job service". 4. **Make sure to copy the API token** before closing the modal. This is the last time you will have access to the plaintext API token! Dynamic DOES NOT have access to the plaintext API token anywhere. If you lose this API token, you will need to create a new one. 5. The token should start with the prefix `dyn_` followed by 56 alphanumeric characters. #### Using the API token Use the token generated through dashboard to programmatically access Dynamic's API by adding it to the `Authentication` header of your HTTP request. Example: ```bash curl curl \ --location 'https://app.dynamic.xyz/api/v0/environments/<>' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer ADD_YOUR_DYN_TOKEN_HERE' ``` ## Standard errors * `400` - Bad Request. The form of the request is invalid. Please check that the path parameters, query parameters, or the request's body contains the correct and expected information defined in our docs. * `401`- Unauthorized. The endpoint that is being accessed requires an `Authorization` header. * `403` - Forbidden. The token authorized for the HTTP call does not have access to the resource defined by the endpoint (eg. the specific environment, allowlist, user, etc.) * `404` - Not found. The path of the requested resource could not be found. Please check that the URL path is correct or that the ID provided is correct. ## Rate Limits Dynamic's API endpoints are subject to rate limits. Refer to [Rate Limits](/developer-dashboard/rate-limits) for more information. # AccessOutcomeEnum # AddDeeplinkUrlRequest # Allowlist # AllowlistEntriesResponse # AllowlistEntry # AnalyticsSessionsByDate # AnalyticsVisitResponse # AnalyticsWalletsBreakdownResponse # AuthModeEnum # AuthSettings # AuthStorageEnum # AuthenticatorTransportProtocol # BadRequest # BaseUser # BillingSubscription # BillingSubscriptionPeriod # BillingSubscriptionPlanTypeEnum # BulkUserCreateResponse # ChainConfiguration # ChainConfigurations # ChainEnum # ChainToken # ChainTokensResponse # ChainalysisCheck # ChainalysisCheckResultEnum # ChainalysisConfiguration # CoinbaseMpcWalletProperties # CompletePasskeyRecoveryRequest # ConnectRequest # CountryCode # CreateEmbeddedWalletParams # CreateEmbeddedWalletSpecificOpts # CreateEmbeddedWalletsRequest # CreateMfaToken # CreateProjectResponse # CreateTokenResponse # CreateTurnkeyEmbeddedWalletSpecificOpts # CreateUserEmbeddedWalletsFromFarcasterRequest # CreateUserEmbeddedWalletsRequest # CreateUserOauthRequest # CreateWalletRequest # Currency # CurrencyType # CustomField # CustomFieldRequest # CustomFieldType # CustomFieldValidValue # CustomFieldValidationRules # CustomFieldsResponse # CustomHostname # CustomHostnameCreateRequest # CustomHostnameStatusEnum # CustomHostnameVerificationRecord # CustomHostnameVerificationType # CustomHostnamesResponse # DeeplinkUrlResponse # DeeplinkUrlsResponse # DnsRecordType # Duration # DynamicJwt # EmailProviderResponse # EmailVerificationCreateRequest # EmailVerificationCreateResponse # EmailVerificationRetryRequest # EmailVerificationVerifyRequest # EmbeddedWalletAuthToken # EmbeddedWalletAuthType # EmbeddedWalletPasscodeClaimRequest # EmbeddedWalletProviderEnum # EmbeddedWalletSecret # EmbeddedWalletSecretWithUpdatedJwt # EmbeddedWalletSecurityMethod # EncodedJwt # EnvironmentEnum # EnvironmentVisitorsResponse # EnvironmentsResponse # ErrorMessageWithCode # Event # EventType # EventTypesResponse # EventsResponse # ExchangeRatesResponse # Export # ExportCreateRequest # ExportCreateRequestFilter # ExportEmbeddedWalletResponse # ExportFormatEnum # ExportModelEnum # ExportStatusEnum # ExportsResponse # ExternalAuth # ExternalAuthSigninRequest # ExternalJwtCheckRequest # ExternalJwtCheckResponse # FarcasterSignInRequest # Forbidden # ForbiddenErrorPayload # ForbiddenWithErrorAndPayload # FrameworkSettings # Gate # GateCreateRequest # GateRule # GateRuleFilter # GateRuleType # GateUpdateRequest # GatesResponse # GetUserPasskeysResponse # HCaptchaSettings # HTTPSUrlOrSNSArn # HardwareWalletEnum # HardwareWalletProperties # HealthcheckResponse # HealthcheckStatus # InitEmailAuthRequest # InitEmailAuthResponse # InitPasskeyRecoveryRequest # InitPasskeyRecoveryResponse # IntegrationSetting # InternalServerError # InternalUserFields # Invite # InviteConflictResponse # InviteSendRequest # InviteStatusEnum # InviteUpdateRequest # InvitesResponse # JwksKey # JwksResponse # JwtBlockchainAccount # JwtPayloadDeprecatedInfo # JwtVerifiedCredential # JwtVerifiedCredentialFormatEnum # Key # KeyResponse # KycFieldType # MFAAuthRecoveryDevicePostRequest # MFAAuthTotpDevicePostRequest # MFADevice # MFADeviceType # MFAGetDeviceResponse # MFAGetRecoveryCodesResponse # MFAListDevicesResponse # MFARegenRecoveryCodesResponse # MFARegisterTotpDeviceGetResponse # MFARegisterTotpDevicePostRequest # MFARegisterTotpDevicePostResponse # MFASettings # MFAUpdateDeviceRequest # MemberResponse # MemberRoleField # MembershipEnvironmentIds # MergeConflicts # MergeUser # MergeUserConflict # MergeUserConflictResolution # MergeUserConflictResolutions # MethodNotAllowed # MfaBackupCodeAcknowledgement # MinifiedDynamicJwt # MobileSettings # NameService # NameServiceData # NativeCurrency # Network # NetworkConfiguration # NetworkConfigurationResponse # NextJsSettings # NextViewEnum # NonEmptyIsoCountryCode # NonEmptyString # NonEmptyStringWith255MaxLength # NonEmptyUrl # NonEmptyUrlWith255MaxLength # NonceResponse # NotFound # OAuthCode # OAuthError # OauthProviderLoginUrl # OauthProviderRequest # OauthRedirectRequest # OauthRedirectRequestIdToken # OauthRedirectUri # OauthRequest # OauthResultRequest # OauthResultResponse # OauthResultStatus # OnrampConfiguration # OptionalHexString # OptionalNonEmptyString # OptionalNonEmptyStringWith255MaxLength # OptionalNonEmptyUrl # OptionalNonEmptyUrlWith255MaxLength # OptionalNullableNonEmptyStringWith255MaxLength # Organization # OrganizationFields # OrganizationMember # OrganizationMembersResponse # OrganizationMfaSettings # OrganizationMfaSettingsResponse # OrganizationRequest # OrganizationResponse # OrganizationsResponse # OriginResponse # OriginsResponse # PasskeyRegistrationCredential # PasskeyStorage # PasswordSourceTypeEnum # PasswordString # PostAllowlistEntriesRequest # PostAllowlistsRequest # PostTokenFields # PrefetchRequest # Project # ProjectEnvironment # ProjectRequest # ProjectSettings # ProjectSettingsChains # ProjectSettingsDesign # ProjectSettingsDesignButton # ProjectSettingsDesignModal # ProjectSettingsDesignWidget # ProjectSettingsGeneral # ProjectSettingsGeneralApps # ProjectSettingsKyc # ProjectSettingsPrivacy # ProjectSettingsSdk # ProjectSettingsSecurity # ProjectsResponse # Provider # ProviderAgreement # ProviderCreateRequest # ProviderEnum # ProviderUpdateRequest # ProviderUrl # ProviderUrlsResponse # ProvidersResponse # PublishEvents # ReactSettings # RegisterSessionKeyRequest # RoleEnum # SdkSettingsRequest # SdkUser # SdkView # SdkViewSection # SdkViewSectionAlignment # SdkViewSectionType # SdkViewType # SdkViewUpdateRequest # SdkViewsResponse # Session # SignInProviderEnum # SmsCountryCode # SmsVerificationCreateRequest # SmsVerificationCreateResponse # SmsVerificationRetryRequest # SmsVerificationVerifyRequest # SocialSignInProvider # SocialSignInProviderEnum # SubscriptionAdvancedScopeEnum # SubscriptionFreeScopeEnum # SupportedOnrampsResponse # SupportedSecurityMethod # SupportedSecurityMethods # TimeUnitEnum # Token # TokenAddress # TokenBalance # TokenCreatedBy # TokenWithRaw # TokensResponse # TooManyRequests # TurnkeySignedRequest # TurnkeyStamp # TurnkeyWalletProperties # Unauthorized # UnprocessableEntity # UnprocessableEntityErrorCode # UnprocessableEntityErrorPayload # UpdateProjectRequest # UpdateProjectResponse # UpdateRecoveryEmailRequest # UpdateSelfResponse # UpdateUserPasskeyRequest # User # UserFields # UserFilterableFieldsEnum # UserIdentifierTypeEnum # UserOauthAccessTokenResponse # UserPasskey # UserResponse # UserSearchFilterParams # UserWalletSelectionRequest # UserWalletsResponse # Username # UsersResponse # ValidCustomHostname # ValidStringQueryParam # VerifyRequest # VerifyResponse # VerifyUnlinkRequest # Visitor # VisitorFilterableFieldsEnum # VisitorSearchFilterParams # VisitorsResponse # Wallet # WalletAdditionalAddress # WalletAddressType # WalletProperties # WalletProviderEnum # WalletPublicKey # Webhook # WebhookCreateRequest # WebhookMessage # WebhookMessageRedeliveryResponse # WebhookMessagesResponse # WebhookUpdateRequest # WebhooksResponse # WhenToImplementEnum # btcWalletString # caip2 # captchaToken # ckbWalletString # deeplinkUrl # dogeWalletString # emailOrEmptyString # kasWalletString # kdaWalletString # ltcWalletString # oAuthAccount # orderBy # origin # phoneNumberOrEmptyString # sixDigitsVerificationToken # uuid # JWTs/Authentication Tokens ## Introduction When an end user connects their wallet, you, the developer, get a [JSON Web Token (JWT)](https://jwt.io/introduction) that can be used to verify some claims about the end user, notably a proof of ownership over a wallet public address. We use the JWT information in the SDK to create the user object and their Verified Credentials so that you can simply interact with the user object to get the information you need, so if you don't need to access the JWT directly, you can skip this page and visit the [Users section](/users) instead. ## Storing JWTs ### Localstorage Once the user has logged in, the JWT gets stored in localstorage under the `dynamic_authentication_token` key. We also store a minified version under the `dynamic_min_authentication_token` key. ### Cookies If you prefer to store the JWT in a HTTPOnly cookie, you might want to use the [Cookie auth feature](/authentication-methods/cookie-authentication). Bear in mind that with Cookie auth turned on, as long as you're still in Sandbox mode, the JWT will still be stored in localstorage but once you move to live mode it won't be, and you will no longer be able to access it using javascript. ## Accessing JWTs ### Fetch JWT from SDK The [getAuthToken](/react-sdk/utilities/getauthtoken) utility function will return the JWT token to you from local storage as long as the user is logged in. It will return undefined otherwise. ### Fetch JWT from Local Storage You can also access the JWT directly from local storage using the following code (note that this will not work if Cookie auth is enabled): ```javascript const token = localStorage.getItem('dynamic_authentication_token'); if (token) { // do something with the token } ``` ## Using JWTs ### JWT Vs User Object Normally, you do not need to use the JWT directly, as all of the information/claims are stored on the user object, which you can learn about in the [Users section](/users). If however you are doing server-side verification, you can use the JWT to verify the user's identity. See the [Server-side verification](/authentication-methods/how-to-validate-users-on-the-backend) page for more information. ### JWT Payload ##### Standard JWT claims: See: [https://www.rfc-editor.org/rfc/rfc7519#section-4.1](https://www.rfc-editor.org/rfc/rfc7519#section-4.1) | Field | Description | | ----- | --------------------------------------------------------------------------------------------- | | aud | Audience for the JWT token. This claim shows what domain of the indended audience of the JWT. | | iss | Issuer of the JWT token. This claim shows app.dynamic.xyz generated and issued the JWT. | | sub | Subject of the JWT token. userId in the deprecated info claim. | | iat | Timestamp when the JWT token was issued. | | exp | Timestamp when the JWT token will expire. | ##### Dynamic-specific claims: These fields are **optional** and you depends on whether you want to collect this information during onboarding. For more information about collecting this information, see [here](/users/information-capture). | alias | Alias field from customer information capture. | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | email | Email field from customer information capture. | | environment\_id | Unique ID of the project environment for the SDK, from [https://app.dynamic.xyz/dashboard/api](https://app.dynamic.xyz/dashboard/api). environmentId in the deprecated info claim. | | given\_name | First name field from customer information capture. firstName in the deprecated info claim. | | family\_name | Last name field from customer information capture. lastName in the deprecated info claim. | | lists | Names of access lists enabled for this user. | | verified\_credentials | List of all [verified credentials](/react-sdk/objects/verified-credential) connected to this user. | | verified\_account | If present, this was the most recently signed and verified account. | #### Example ```JSON{ "alias": "john", "aud": "https://dashboard.hello.xyz", "verified_credentials": [ { "address": "0x000123abc", "chain": "eip155", "id": "af615228-99e5-48ee-905d-4575f0a6bfc9", "wallet_name": "metamask" } ], "email": "[[email protected]](/cdn-cgi/l/email-protection)", "environment_id": "fb6dd9d1-09f5-43c3-8a8c-eab6e44c37f9", "family_name": "bot", "given_name": "jon", "iss": "app.dynamic.xyz/fb6dd9d1-09f5-43c3-8a8c-eab6e44c37f9", "lists": [ "Community dashboard acess list" ], "sub": "d261ee91-8ea0-4949-b8bb-b6ab4f712a49", "verified_account": { "address": "0x000123abc", "chain": "eip155", "id": "af615228-99e5-48ee-905d-4575f0a6bfc9", "wallet_name": "metamask" }, "iat": 1660677597, "exp": 1660684797 } ``` ## Using your own JWTs If you have your own authentication system, you can use your own JWTs to authenticate users in Dynamic. This can be done by exchanging your token for a Dynamic JWT. This will return Dynamic’s standard sign-in artifacts (i.e., a minified JWT and user). Checkout the [Third-party Authentication](/authentication-methods/third-party-auth) page for more information on how to set up and use this feature. # Sign Up with Branded Wallets ## Enable Branded Wallet Signup/Login The first step is to enable the appropriate chains that you'd like to support and add the appropriate connectors to your app. The following [chains and networks configuration guide](/chains/enabling-chains) will show you how to do both. You can use the default RPC URLs that we provide for each chain/network, but if you'd like to configure your own, please follow [this RPC guide](/chains/rpc-urls). In [the Log in & User Profile section of the dashboard](https://app.dynamic.xyz/dashboard/log-in-user-profile), toggle on Wallet Log in under "Branded Wallets" and you're good to go! ## Basic Configuration In the same section of the dashboard where you enabled Branded Wallets, you can also configure the following: * Multi-Wallet: This option, when toggled on, allows your end users to have more than one connected wallet to their account and change between them. In this way users don't have to sign out and back in again if they want to use a different wallet, they simply switch between them. You can learn more about Multi-Wallet on [the overview page](/wallets/advanced-wallets/multi-wallet). * Hide Network: This is used in conjunction with the UI components, specifically [the DynamicUserProfile](/react-sdk/components/dynamicuserprofile) which is available on its own but also bundled as part of [DynamicWidget](/react-sdk/components/dynamicwidget). By default, the user profile shows the network the user is currently connected to and allows them to switch to another. If you want to hide this, simply toggle this option on. * WalletConnect: Configuration for [https://walletconnect.com/](https://walletconnect.com/) ## Further Configuration When you enabled Branded Wallets, by default you will be in what's called "connect-and-sign" mode. It's worth reading about the implications of this in [the overview of authentication modes](/wallets/advanced-wallets/connected-vs-authenticated) to decide what's right for your use case. There's a bunch of further customizations you can do for the Branded Wallet experience including things like [sorting and filtering wallets](/wallets/advanced-wallets/sort-and-filter-wallets), so it's worth reviewing [the advanced wallets section of the docs](/wallets/advanced-wallets) in depth when you're ready. # Adding Captcha Protection ## Summary Setting up a captcha can help protect your Dynamic-enabled site from bots. We currently support [hCaptcha](https://www.hcaptcha.com/) as our captcha provider. Here is an example of how it looks like when enabled in Dynamic's SDK. ## Setting up hCaptcha To get started, you must first create an hCaptcha account. 1. **Sign up for a new account on [hCaptcha](https://www.hcaptcha.com/)** - We recommend considering upgrading to the "Pro" plan, which allows for "passive" and "friction-free" modes. 2. **Add a new site** - Make sure the hostname corresponds to the domain you are using the Dynamic SDK on. For example, if you plan to set up the Dynamic SDK in `app.myawesomesite.com`, then you should add this value to the Hostname sections in hCaptcha. ![](https://mintlify.s3-us-west-1.amazonaws.com/dynamic-docs/images/hcaptcha-general.png) 3. **Get your site key** - This is used by the Dynamic SDK to communicate with hCaptcha and display a captcha challenge before the verification step in the wallet sign-in flow. Copy this value, which we will need to set up in Dynamic. ![](https://mintlify.s3-us-west-1.amazonaws.com/dynamic-docs/images/hcaptcha-site-key.png) 4. **Get your secret key** - This is used by the Dynamic server-side backend to verify the captcha result from the SDK, and is never leaked to the SDK. To get your secret key, click on your account profile on the upper right corner and select "Settings". You should see your plaintext secret key, which you should also copy to set up in Dynamic. ![](https://mintlify.s3-us-west-1.amazonaws.com/dynamic-docs/images/hcaptcha-settings-button.png) ## Setting up Dynamic captcha Now that we have hCaptcha set up, we can move on to final configuration within Dynamic. 1. **Log in to Dynamic Dashboard.** On the right navigation bar, click on "Configurations" then select "hCaptcha" under "Onboarding Fields" 2. **Add your site key and secret key from hCaptcha** - See previous steps on how to set up your hCaptcha credentials. 3. **Enable** - When you are ready to enable the captcha, please make sure to switch the "enable" toggle. # Cookie Based Authentication #### Introduction Dynamic can now be configured to set a secure, HttpOnly cookie that can be used for authenticating with Dynamic’s backend. This will contain a minified version of our JWT token. This feature would also allow your site's end users to sign in on one subdomain and go to another subdomain without that end user needing to log in again using the same Dynamic environment ID. #### Approach Dynamic will require the setup of a custom hostname. This is a subdomain that you own, but pointed by DNS CNAME to Dynamic's API. This will allow Dynamic's backend to set secure, HttpOnly cookies on your domain. For example, if your Dynamic-powered site is [https://app.example.io](https://app.example.io), the custom hostname you could use is [https://auth.example.io](https://auth.example.io). This would allow your users to sign in with Dynamic on [https://app.example.io](https://app.example.io), receive an HttpOnly secure cookie for `.example.io`. This cookie can then be used on any subdomain ending with `.example.io`, such as [https://marketplace.example.io](https://marketplace.example.io) and [https://shop.example.io](https://shop.example.io). #### Steps The following steps would be required to properly set up cookie-based authentication. 1. Go to the dashbaord security page and configure a custom domain. 2. Provide us with a subdomain you intend to use. We need this so we can set a first party cookie on your behalf on our backend. Suggestion here is to prefix with auth. For instance for `example.io`, you can potentially use `auth.example.io`. 3. Follow the instructions to set up DNS. There should be three DNS records: 2 TXT records for site and certificate verification, and 1 CNAME record to proxy the custom subdomain of your choice. 4. Note: In `sandbox`, we will also attempt to set the cookie from the SDK frontend. This will ensure continued support for local development and other preview environments. 5. Once DNS is validated, update the `apiBaseUrl` prop in `DynamicContextProvider` settings. For example: ```TypeScript ... ``` 7. Enable the cookies toggle. When this is enabled in `live`, Dynamic **WILL NO LONGER** return a JWT to store in local storage. The auth token will only be set on a cookie. # Sign Up with Email/Social/SMS ### Introduction When it comes to onboarding users, having a flexible sign-up flow that can accommodate different preferences is key. Whether users prefer to sign up with their email, phone number, social media accounts, or directly with a wallet, providing the options that fit your user's needs can make the onboarding process smoother, more user-friendly, and increase conversion. That is why we are offering the flexibility to design the sign up screen to suit your needs. You can now choose whether you want users to sign up with their email, phone number, social accounts, or with wallets. You can configure this as needed. If you then want to generate a wallet for your users when they sign up using email, social or sms, please refer to [the embedded wallets section](/wallets/embedded-wallets/dynamic-embedded-wallets) after configuring email/social/sms below. #### Sign up with Email Simply toggle on "Email" in [the Log in & User Profile section of the dashboard](https://app.dynamic.xyz/dashboard/log-in-user-profile). #### Sign up with Social Sign up/sign in with Apple, Discord, Facebook, Farcaster, Github, Google, Telegram, Twitch or Twitter! Similar to email, you can toggle and configure each social provider in the [social providers section of the dashboard](https://app.dynamic.xyz/dashboard/log-in-user-profile). Configuration guides for individual social signup options can be found in [the social providers section of the docs](/social-providers/overview). Note that when configuring any social provider, you can adjust [the `social` prop](/react-sdk/providers/dynamiccontextprovider#social) in the `DynamicContextProvider` component to customize the user experience i.e. whether you use a redirect or popup. #### Sign up with SMS Toggle on "Phone Number" in [the Log in & User Profile section of the dashboard](https://app.dynamic.xyz/dashboard/log-in-user-profile). By default, you can use Dynamics credentials to send SMS messages to your users. However, if you want to send beyond US & Canada, you will need to set up your own Twilio account. In order to do this, you toggle off "Use Dynamic's credentials" and a section will open up for you, where you can enter your own credentials. {/* ## SMS & Embedded Wallets When you enable SMS sign-up, you can also enable embedded wallets for your users. This means that when a user signs up with their phone number, they will also receive a wallet that they can use to interact with your application. In order to ensure your end users are adequately protected against attacks like sim swaps, we also require a second factor before the wallet is generated. This can be [a passkey](/wallets/embedded-wallets/passkeys), or [a one time code](/wallets/embedded-wallets/one-time-codes). _We highly recommend using passkeys, which shortens the onboarding flow._ If however, the user loses or deletes their passkey, they will be locked out of their wallet. To prevent this, we recommend prompting users to add an email address to their account. This way, they can recover their wallet if they lose their passkey. When using one time codes, the user will automatically prompted to add their email. */} # Server-side verification When an end user connects their wallet, you, the developer, get a [JSON Web Token (JWT)](https://jwt.io/introduction) that can be used to verify some claims about the end user, notably a proof of ownership over a wallet public address. Upon authentication, we generate a JWT signed with a private key (using RS256 algorithm) that is unique to you. In turn, you can use the associated public key (found in the [API tab](https://app.dynamic.xyz/dashboard/api) of your developer dashboard) to ensure that the token is authentic and hasn't been tampered with. In other words, if a JWT issued by Dynamic can be successfully verified with your public key, the information it contains can be trusted. You can do this in multiple ways. #### Option 1: Leverage [NextAuth](https://next-auth.js.org/) If you are using Next.js, you can easily [integrate the NextAuth library with Dynamic](/guides/frameworks/next-auth) to perform server-side verification and then use a session client-side. #### Option 2: Leverage [Passport.js](https://www.passportjs.org) We offer an official [passport-dynamic](https://github.com/dynamic-labs/passport-dynamic) extension. #### Option 3: Do-It-Yourself Verification 1. Get the JWT through the Dynamic SDK with an [authToken](/react-sdk/utilities/getauthtoken). 2. Send the authToken to the server as a Bearer token ```JavaScript import { useEffect, useState } from "react"; export const useFetch = (authToken: string | null) => { const [data, setData] = useState({}); useEffect(() => { const fetchApi = async () => { await fetch("http://localhost:9000/api", { headers: { Authorization: `Bearer ${authToken}`, }, }).then(response => response.json()).then(setData); } fetchApi() }, [authToken]); return { data }; }; ``` 3. Install the [node-jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) and [jwks-rsa](https://www.npmjs.com/package/jwks-rsa) packages 4. Validate the JWT on your server by fetching the public key from the [JWKS endpoint](/api-reference/endpoints/sdk/getJwksByEnvironmentId.mdx) API endpoint and verifying the encoded JWT against the public key: ```TypeScript import jwt, { JwtPayload } from 'jsonwebtoken'; import { JwksClient } from 'jwks-rsa'; // can be found in https://app.dynamic.xyz/dashboard/developer/api const jwksUrl = `https://app.dynamic.xyz/api/v0/sdk/${YOUR_DYNAMIC_ENV_ID}/.well-known/jwks` // The clinet should be initalized as const client = new JwksClient({ jwksUri: jwksUrl, rateLimit: true, cache: true, cacheMaxEntries: 5, // Maximum number of cached keys cacheMaxAge: 600000 // Cache duration in milliseconds (10 minutes in this case))} }); const signingKey = await client.getSigningKey(); const publicKey = signingKey.getPublicKey(); const decodedToken: JwtPayload = jwt.verify(encodedJwt, publicKey, { ignoreExpiration: false, }) as JwtPayload; if (decodedToken.scopes.includes('requiresAdditionalAuth')) { // Either reject or handle the scopes appropriately. // `requiresAdditionalAuth` is the scope used to indicate that JWT requires additional verification such as MFA. throw new Error('Additional verification required'); } console.log(decodedToken) // { iss: 'xxxx', exp: nnnn, ... } ``` This uses the following libraries: * [jwks-rsa](https://www.npmjs.com/package/jwks-rsa): Provides client to interact and parse JWKS key signing data for a JWT. * [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken): Provides library to encode/decode and validate a JWT token. # Multi-Factor Authentication (MFA) ## Introduction This guide will show you how to enable Dynamic's Account level multi-factor authentication in your app. Dynamic offers two different types of multi-factor authentication: account level and transaction level. At the account level, users must complete 2FA on login, while at the transaction level, they must complete 2FA when creating a transaction. You can learn more about transaction-level multi-factor authentication here. (And yes, we know it might be a bit confusing. Just remember: one MFA is for logging in, the other is for doing stuff after logging in. Think of it like locking your front door and then locking the safe inside!) ## Supported methods Dynamic currently supports these Account level methods: * Authenticator app (e.g. Google Authenticator or Authy) * Passkeys (coming soon) * SMS (coming soon) ## Setup 1. Make sure you are on the latest Dynamic packages (V3) 2. Go to the [Security page](https://app.dynamic.xyz/dashboard/security) in your developer Dashboard. 3. In the Account MFA section, enable the Authenticator Apps toggle, then click Save Changes. 4. Optionally, you can require users to MFA on signup by clicking on the settings gear to the right of the Authenticar Apps toggle, then toggle on "Require at onboarding" That's it! Make sure you are using the same environment id from the [SDK & API Keys page](https://app.dynamic.xyz/dashboard/developer/api) in your app. When you sign in to your app, you will be prompted to MFA if you toggled on "Require at onboarding", otherwise you will be able to optionally add MFA from the user profile section of the Dynamic widget. ## Supporting users who lose access to their Authenticator App Please ensure you only delete MFA devices after confirming the identity of your end users. In the event that one of your users contacts you that they lost access to their authenticator device, you can delete their device by going to the User Management table. 1. Go to the User Management table. 2. Find the user by searching based on email, username, or other verified credentials. 3. Open the details panel and click the button to delete the authenticator devices. 4. If MFA is required, then on the next login the user will be required to register a new device. Otherwise, the user can optionally add a device after logging in. # Third-party Authentication ### This is an enterprise-only feature. Please contact us [in slack](https://dynamic.xyz/slack) or via email ([hello@dynamic.xyz](mailto:hello@dynamic.xyz)) to enable. #### Introduction If you have built your own authentication system or use other auth providers outside Dynamic, you may want to keep using those services while taking advantage of Dynamic’s product to enable web3-based functionality and interactions. Third-party authentication allows you to do this by exchanging your token from a JWT issuer to "sign-in" or "link" to Dynamic. #### Approach Dynamic provides a new API endpoint and utility hook `useExternalAuth`, to allow sign-in or linking with an external 3rd party JWT by exchanging it for a Dynamic JWT. This will return Dynamic’s standard sign-in artifacts (ie, minified JWT and user). At a high level, this will do the following steps: 1. Verify the authenticity of the JWT by getting the public key from a JWKS endpoint provided by you, and using this public key to verify the JWT. 2. Require you to provide exact value for either the `iss` (issuer) JWT claim. If the value of this field deviates from that is provided in the project environment’s configuration, we will reject the JWT. 3. Dynamic will also require the `sub` (subject, or user ID) field be provided. These will correspond to the your user ID. These will be mapped to the similar user model in Dynamic. 4. Dynamic will also require `exp` (expires at) JWT claim from external JWT. Dynamic will ensure that this `exp` claim is respected with timeouts on the SDK. 5. Once signed in using this external JWT, we will create an **new verified credential** of type `externalAuth`, letting us know that the user has an external authentication mechanism they used to verify their account. This should have `externalUserId` with the value of the JWT’s `sub`. 6. Optional verified credential data, such as e-mail sign in can be provided as part of the JWT. This would allow Dynamic to create an email verified credential tied to the Dynamic user on our side. #### Workflow ![](https://mintlify.s3-us-west-1.amazonaws.com/dynamic-docs/images/swimlanes-e22f25180d42b5d9494a3d58f2f1cbb5.png) #### Dashboard Configuration To access this page, navigate to the [Third-Party Auth](https://app.dynamic.xyz/dashboard/developer/third-party-auth) page in your dashboard. 1. Provide values for the following fields: * `iss` (required): Standard JWT claim for the "issuer" of the JWT. This should be the entity that issued the token. This is typically a URL, but can be a valid constant string. * `jwksUrl` (required): This is a publicly-accessible URL that returns the JWT's signer public key in the standard [JWKS format](https://datatracker.ietf.org/doc/html/rfc7517). This is used to verify the signatures of your JWTs. * `aud` (optional): Standard JWT claim for the "audience" of the JWT. This should be the intended recipient of the token. This is typically a URL, but can be a valid constant string. * `cookieName` (optional): For clients that use cookie-based authentication for their 3rd party auth and who have no acccess to the raw JWT on the frontend, we provide a way for clients to specify the cookie name to expect the JWT to be stored. 2. When you are ready, enable the feature using the toggle. 3. Additionally, we provide a way for you to check a JWT against your saved settings, and we will return the errors, if any. #### Frontend Implementation After properly configuring the settings for this feature, you should be able to "sign-in" with a non-Dynamic JWT token by calling the `signInWithExternalJwt` method from the `useExternalAuth` hook. ```TypeScript const { signInWithExternalJwt } = useExternalAuth(); try { // `externalUserId`: User ID in the external auth system // `externalJwt`: Raw encoded JWT issued by external auth system const userProfile = await signInWithExternalJwt({ externalUserId, externalJwt }); if (userProfile) { // You should be logged in at this point } } catch (e: any) { console.error('Dynamic login failed:', e); } ``` Similarly, you can verify the user using the verifyWithExternalJwt method: ```TypeScript const { verifyWithExternalJwt } = useExternalAuth(); try { const verifiedProfile = await verifyWithExternalJwt({ externalUserId, externalJwt }); if (verifiedProfile) { // User verification successful } } catch (e: any) { console.error('Dynamic verification failed:', e); } ``` # Bridge Widget The `DynamicBridgeWidget` component allows you to handle multi chain bridging See it in action on [https://starkgate.starknet.io/](https://starkgate.starknet.io/) ## Background This widget gives you a full UI to handle the Bridge use case (multi chain bridging). It will allow you to connect multiple wallets from different chains and bridge assets between them. The video above shows our Bridge Widget in action on our demo site. Here you can see how to connect two wallets from different chains and then you can see that you can easily toggle the wallets so different wallets can sign. For this multi-chain bridge, this flow is custom built for this scenario. It is different from our multiwallet widget, since only 1 wallet of each chain is desired. Additionally, this bridge widget supports the following: 1. It is a Connect-only multiwallet widget where all relevant information about the connected wallets are stored in Local Storage instead of the DB 2. It directs users to add a wallet from 1 chain, and then a second chain 3. It is flexible in that: * A user can easily add or remove wallets * It can toggle between the wallets so defining the Depositing wallet vs the Withdrawl wallet is simple. * It supports network switching. * It supports unlinking through our widget or via a hook * The event listeners work on both wallets, so your dapp is always up to date with the proper account and network. ## Usage To get the bridge component setup, you’ll want to have [your desired chains configured](/chains/enabling-chains.mdx), for example Ethereum and Starknet. Then, in your `index.tsx` (or wherever you render `DynamicContextProvider`, specify the `initialAuthenticationMode ` and [`bridgeChains`](/react-sdk/objects/wallets-by-chain) prop like so: ```typescript import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core"; import { EthereumWalletConnectors } from "@dynamic-labs/ethereum "; import { StarknetWalletConnectors } from "@dynamic-labs/starknet"; ``` Then, in `app.tsx`: ```typescript import { DynamicBridgeWidget } from "@dynamic-labs/sdk-react-core"; export default function App() { return (
); } ``` And that's it! Now you're rendering our bridge widget. ## bridgeChains Primarily used for [bridging](/building-bridges/dynamic-bridge-widget) purposes, this object is passed as a prop to the `settings` in the [`DynamicContextProvider` component](/adding-dynamic/dynamic-context-provider). It creates a situation where the `isFullyConnected` prop on `useDynamicContext` hook is true only if the user has connected at least one wallet per chain, from each chain in the bridgeChains array. ### Description An Array of objects, in which each object contains the chain name to be connected. | Field | Description | | ------------- | ----------- | | chain: string | Chain name | ### Example ```jsx [ { chain: "EVM", }, { chain: "STARK", }, ]; ``` # Custom Cosmos network You can enable any Cosmos network that we do not currently support in our dashboard by passing an array of `GenericNetwork` to the `DynamicContextProvider`'s `overrides.cosmosNetworks` settings. This can be done in two different ways: 1. By passing an array of `GenericNetwork`, it completely overrides whatever networks were received from your dashboard configurations and uses that array instead. 2. By passing a method with signature `(dashboardNetworks: GenericNetwork[]) => GenericNetwork[]`, you can use this callback to first receive the array of networks that was sent from your dashboard configurations, and then return the array of networks you want the app to use. The second approach is best for making adjustments to the networks you get from our dashboard (like changing rpc urls), as well as when you want to hide some specific networks. If you're just trying to merge new networks with the ones from dashboard, we have a helper function that will make that easier: ```TypeScript import { mergeNetworks } from '@dynamic-labs/sdk-react-core'; const DynamicSettings = { overrides: { cosmosNetworks: (networks) => mergeNetworks(myCosmosNetworks, networks), } }; ``` > Note that the order of the params for `mergeNetworks` matters: the first param takes precedence in case of a conflict. ## Example The following example sets Sei for the application. Remember to enable the cosmos blockchain in the dashboard ```TypeScript // we are setting the chainId and networkID to a random ID that will not conflict with other active chains in Dynamic. const cosmosNetworks= [ { blockExplorerUrls: ["https://www.seiscan.app/pacific-1"], chain: 'Sei', chainId: '404', iconUrls: ['https://app.dynamic.xyz/assets/networks/sei.svg'], lcdUrl: 'https://rest.wallet.pacific-1.sei.io', name: 'pacific-1', nativeCurrency: { decimals: 18, denom: 'usei', name: 'Sei', symbol: 'Sei', }, networkId: '404', rpcUrls: ['https://rpc.wallet.pacific-1.sei.io'], shortName: 'Sei', vanityName: 'Sei', } ]; const App = () => ( ); export default App; ``` ## Type Reference ### Definition | Attribute | Value | Required/Optional | | ---------------------- | ---------------- | ----------------- | | blockExplorerUrls | `string[]` | Required | | chainId | `number` | Required | | name | `string` | Required | | iconUrls | `string[]` | Required | | nativeCurrency | `NativeCurrency` | Required | | networkId | `number` | Required | | privateCustomerRpcUrls | `string[]` | Optional | | rpcUrls | `string[]` | Required | | vanityName | `string` | Optional | #### NativeCurrency | Attribute | Value | Required/Optional | | --------- | -------- | ----------------- | | decimals | `number` | Required | | name | `string` | Required | | symbol | `string` | Required | | denom | `string` | Optional | # Embedded Wallet Chains This guide expands on the [integrating chains section](/chains/enabling-chains), and shows you what SDK setup you need to have to enable embedded wallets for your users. ## Prerequisites You have enabled embedded wallets in the dashboard already, for more information on that, check out the [embedded wallets guide](/wallets/embedded-wallets/dynamic-embedded-wallets). ## Initial setup You can use embedded wallets with Ethereum, Solana or both! Therefore, whichever one you choose, you need to make sure you have the correct walletConnectors are installed and added to the walletConnectors array in the SDK settings. For Ethereum, you need to install the `@dynamic-labs/ethereum` package: ```bash npm npm i @dynamic-labs/ethereum ``` ```bash yarn npm i @dynamic-labs/ethereum ``` Then, you need to add the `EthereumWalletConnectors` to the `walletConnectors` array in the SDK settings: ```jsx import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'; import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'; const App = () => ( ); ``` For Solana, you need to install the `@dynamic-labs/solana` package: ```bash npm npm i @dynamic-labs/solana ``` ```bash yarn npm i @dynamic-labs/solana ``` Then, you need to add the `SolanaWalletConnectors` to the `walletConnectors` array in the SDK settings: ```jsx import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'; import { SolanaWalletConnectors } from '@dynamic-labs/solana'; const App = () => ( ); ``` That's it! You've set up your chains correctly in order to create embedded wallets for your users. Click here to learn how to enable chains for Smart Wallets! # Enabling Chains ## Supported Chains/Networks Below is a list of the supported chains/networks, but you can also view them more visually in the [dashboard](https://app.dynamic.xyz/dashboard/chains-and-networks): If you don't see the chain/network you need and it's not EVM compatible, just [let us know](https://dynamic.xyz/slack)! 1. EVM: We support all EVM networks. You can currently turn on the following via the dashboard (simply go to the [EVM tab](https://app.dynamic.xyz/dashboard/chains-and-networks#evm) in your dashboard and flip the toggle). For any not mentioned below, you can easily add them manually using [our evmNetworks prop](/chains/network-switching). * Arbitrum * Aurora * Avalanche C chain * BNB Smart Chain * Base * Berachain * Celo * Chiliz * Cronos * EON * Ethereum * Fantom * Gnosis * Moonbeam * Optimism * Palm * Polygon * Scroll * Zora * zkSync 2. Solana 3. Eclipse 4. Bitcoin 5. Flow 6. StarkNet 7. Cosmos 8. Algorand ## Enabling a Chain/Network To integrate a specific chain/network, you should first [enable it in the dashboard](https://app.dynamic.xyz/dashboard/chains-and-networks). You'll also see that you can add custom RPC URLs for each network. Each provider will use the RPC configured in the Dashboard if present, otherwise they fall back to public RPCs urls. By default, all EVM and Solana networks have public default providers as shown in this table: | Network | Public RPC Url | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | Ethereum | [https://cloudflare-eth.com](https://cloudflare-eth.com) | | Optimism | [https://mainnet.optimism.io](https://mainnet.optimism.io) | | Gnosis Chain | [https://rpc.gnosischain.com](https://rpc.gnosischain.com) | | Aurora | [https://mainnet.aurora.dev](https://mainnet.aurora.dev) | | Polygon | [https://polygon-rpc.com](https://polygon-rpc.com) | | Palm | [https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b](https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b) | | BNB Smart Chain | [https://arb1.arbitrum.io/rpc](https://arb1.arbitrum.io/rpc) | | Solana | [https://api.mainnet-beta.solana.com](https://api.mainnet-beta.solana.com) | | Eclipse | [https://mainnetbeta-rpc.eclipse.xyz](https://mainnetbeta-rpc.eclipse.xyz) | Once your chains are enabled and you're happy with your RPC providers, you're going to want to add the appropriate Wallet Connector to the Dynamic Context Provider that you integrated when [getting started](/adding-dynamic/adding-the-sdk). Each chain has it's own wallet connector, and there are also some add on wallet connectors used to enable things like smart wallets. Follow the steps below and you'll be up and running in no time! Below is a list of all the available wallet connectors and their corresponding packages. | Package Name | Chain | WalletConnector to include | | :--------------------- | :------ | ---------------------------------------------------------------- | | @dynamic-labs/ethereum | EVM | `EthereumWalletConnectors` | | @dynamic-labs/algorand | ALGO | `AlgorandWalletConnectors` | | @dynamic-labs/solana | SOL | `SolanaWalletConnectors` or `SolanaWalletConnectorsWithConfig` | | @dynamic-labs/eclipse | ECLIPSE | `EclipseWalletConnectors` or `EclipseWalletConnectorsWithConfig` | | @dynamic-labs/flow | FLOW | `FlowWalletConnectors` | | @dynamic-labs/starknet | STARK | `StarknetWalletConnectors` | | @dynamic-labs/cosmos | COSMOS | `CosmosWalletConnectors` | | @dynamic-labs/bitcoin | BTC | `BitcoinWalletConnectors` | ##### EVM Addon Wallets | Package Name | Which Wallets | WalletConnector to include | | :------------------------ | :------------ | :----------------------------- | | @dynamic-labs/magic | *magic* | `MagicWalletConnectors` | | @dynamic-labs/blocto-evm | *blocto* | `BloctoEvmWalletConnectors` | | @dynamic-labs/starknet | STARK | `StarknetWalletConnectors` | | @dynamic-labs/ethereum-aa | ZeroDev | `ZeroDevSmartWalletConnectors` | EthereumWalletConnectors (@dynamic-labs/ethereum) also includes all EVM compatible chains including layer 2's i.e. Base as well as [Dynamic Embedded Wallets](/wallets/embedded-wallets/dynamic-embedded-wallets). Install 1 or more wallet connectors from the packages listed above. Here is an example for Ethereum and Solana: ```bash npm npm i @dynamic-labs/ethereum @dynamic-labs/solana ``` ```bash yarn yarn add @dynamic-labs/ethereum @dynamic-labs/solana ``` Add to an array in your settings under `walletConnectors`. Here is an example for Ethereum and Solana: ```jsx import { DynamicContextProvider, DynamicWidget} from '@dynamic-labs/sdk-react-core'; import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'; import { SolanaWalletConnectors } from '@dynamic-labs/solana'; const App = () => ( ); export default App; ``` ## Configurable Wallet Connectors Some wallet connectors come with a configurable alternative. This is useful if you want to customize the wallet connector to your needs. > For example, you can pass a `ConnectionConfig` to set the commitement level or define HTTP request headers for Solana and Eclipse. See an example of how to use the configurable wallet connector for Solana: ```jsx import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'; import { SolanaWalletConnectorsWithConfig } from '@dynamic-labs/solana'; {...} ``` Here are our available configurable wallet connectors: | Chain | Wallet Connector with Config | Type of Wallet Connector with Config | | :------ | :---------------------------------- | :-------------------------------------------------------- | | Solana | `SolanaWalletConnectorsWithConfig` | `(connectionConfig: ConnectionConfig) => WalletConnector` | | Eclipse | `EclipseWalletConnectorsWithConfig` | `(connectionConfig: ConnectionConfig) => WalletConnector` | > `ConnectionConfig` is the object type that can be passed as second argument to` @solana/web3.js`'s `Connection` constructor. > You can find more information about it [here](https://solana.com/docs/clients/javascript-reference#connection). Click here to learn how to enable chains for embedded wallets! # Custom EVM networks For adding a custom EVM networks with Wagmi see: [WAGMI - adding custom networks](https://docs.dynamic.xyz/adding-dynamic/using-wagmi#adding-custom-networks) You can enable any EVM network that we do not currently support out of the box by passing an array of `EvmNetwork` to the `DynamicContextProvider`'s `overrides.evmNetworks` settings. This can be done in two different ways: 1. By passing an array of `EvmNetwork`, it completely overrides whatever networks were received from your dashboard configurations and uses that array instead. 2. By passing a method with signature `(dashboardNetworks: EvmNetwork[]) => EvmNetwork[]`, you can use this callback to first receive the array of networks that was sent from your dashboard configurations, and then return the array of networks you want the app to use. The second approach is best for making adjustments to the networks you get from our dashboard (like changing rpc urls), as well as when you want to hide some specific networks. If you're just trying to merge new networks with the ones from dashboard, we have a helper function that will make that easier: ```TypeScript import { mergeNetworks } from '@dynamic-labs/sdk-react-core'; const DynamicSettings = { overrides: { evmNetworks: (networks) => mergeNetworks(myEvmNetworks, networks), } }; ``` > Note that the order of the params for `mergeNetworks` matters: the first param takes precedence in case of a conflict. ## Example The following example sets the Ethereum mainnet and Polygon as supported networks for the application. A comprehensive list of networks can be found at [chainlist.org](https://chainlist.org) ```TypeScript // Setting up list of evmNetworks const evmNetworks = [ { blockExplorerUrls: ['https://etherscan.io/'], chainId: 1, chainName: 'Ethereum Mainnet', iconUrls: ['https://app.dynamic.xyz/assets/networks/eth.svg'], name: 'Ethereum', nativeCurrency: { decimals: 18, name: 'Ether', symbol: 'ETH', iconUrl: 'https://app.dynamic.xyz/assets/networks/eth.svg', }, networkId: 1, rpcUrls: ['https://mainnet.infura.io/v3/'], vanityName: 'ETH Mainnet', }, { blockExplorerUrls: ['https://etherscan.io/'], chainId: 5, chainName: 'Ethereum Goerli', iconUrls: ['https://app.dynamic.xyz/assets/networks/eth.svg'], name: 'Ethereum', nativeCurrency: { decimals: 18, name: 'Ether', symbol: 'ETH', iconUrl: 'https://app.dynamic.xyz/assets/networks/eth.svg', }, networkId: 5, rpcUrls: ['https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161'], vanityName: 'Goerli', }, { blockExplorerUrls: ['https://polygonscan.com/'], chainId: 137, chainName: 'Matic Mainnet', iconUrls: ["https://app.dynamic.xyz/assets/networks/polygon.svg"], name: 'Polygon', nativeCurrency: { decimals: 18, name: 'MATIC', symbol: 'MATIC', iconUrl: 'https://app.dynamic.xyz/assets/networks/polygon.svg', }, networkId: 137, rpcUrls: ['https://polygon-rpc.com'], vanityName: 'Polygon', }, ]; const App = () => ( ); export default App; ``` ## Type Reference ### Definition | Attribute | Value | Required/Optional | | ---------------------- | ---------------- | ----------------- | | blockExplorerUrls | `string[]` | Required | | chainId | `number` | Required | | name | `string` | Required | | iconUrls | `string[]` | Required | | nativeCurrency | `NativeCurrency` | Required | | networkId | `number` | Required | | privateCustomerRpcUrls | `string[]` | Optional | | rpcUrls | `string[]` | Required | | vanityName | `string` | Optional | #### NativeCurrency | Attribute | Value | Required/Optional | | --------- | -------- | ----------------- | | decimals | `number` | Required | | iconUrl | `string` | Optional | | name | `string` | Required | | symbol | `string` | Required | | denom | `string` | Optional | # Switching Networks ### Usage Using the primaryWallet provided by [useDynamicContext](/react-sdk/hooks/usedynamiccontext), you have two useful methods for network switching: Available on the connector object for the wallet.Whether the connector supports network switching. Available directly on the wallet object. Switch to another network by providing either the network name or chain id. When calling `switchNetwork` with a connector supporting network switching, the SDK will either request the user to confirm the network switch or add the network if it was not previously set. ### Example ```TypeScript const { primaryWallet } = useDynamicContext(); if (primaryWallet?.connector.supportsNetworkSwitching()) { await primaryWallet.switchNetwork(137); console.log("Success! Network switched"); } ``` ![1440](https://mintlify.s3-us-west-1.amazonaws.com/dynamic-docs/images/network-switching.png "Metamask network switching prompt") # Using RPC Providers ## Summary We provide the [`useRpcProviders` hook](/react-sdk/hooks/userpcproviders) that allows direct access to RPC providers for EVM & Solana. Rpc providers can be used to make RPC calls to the blockchain while also providing convenience methods without going through a wallet. Each provider will use the RPC configured in the Dashboard if present, otherwise they fall back to public RPCs urls. By default, all EVM and Solana networks have public default providers as shown in this table: | Network | Public RPC Url | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | Ethereum | [https://cloudflare-eth.com](https://cloudflare-eth.com) | | Solana | [https://api.mainnet-beta.solana.com](https://api.mainnet-beta.solana.com) | | Optimism | [https://mainnet.optimism.io](https://mainnet.optimism.io) | | Gnosis Chain | [https://rpc.gnosischain.com](https://rpc.gnosischain.com) | | Aurora | [https://mainnet.aurora.dev](https://mainnet.aurora.dev) | | Polygon | [https://polygon-rpc.com](https://polygon-rpc.com) | | Palm | [https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b](https://palm-mainnet.infura.io/v3/3a961d6501e54add9a41aa53f15de99b) | | BNB Smart Chain | [https://arb1.arbitrum.io/rpc](https://arb1.arbitrum.io/rpc) | ## Dashboard Configuration To enter your provider url for a given network: 1. Go to the [Chains & Networks](https://app.dynamic.xyz/dashboard/chains-and-networks) page in your Dashboard. 2. Click on the chain to open the details tab 3. Click the down down arrow to expand a network 4. Enter your Provider Url 5. Click the test button to check url ## Usage You are able to use the [`useRpcProviders` hook](/react-sdk/hooks/userpcproviders) to obtain an object with rpc providers, and this hook expects a selector parameter that you must use to select either EVM or Solana rpc providers. ```typescript import { useRpcProviders } from '@dynamic-labs/sdk-react-core' import { evmProvidersSelector } from '@dynamic-labs/ethereum-core' import { solanaProvidersSelector } from '@dynamic-labs/solana-core' const App = () => { const evmProviders = useRpcProviders(evmProvidersSelector) const solanaProviders = useRpcProviders(solanaProvidersSelector) } ``` The hook returns either [EvmRpcProviderMethods](/react-sdk/objects/EvmRpcProviderMethods) or [SolanaRpcProviderMethods](/react-sdk/objects/SolanaRpcProviderMethods), with the following fields: The provider for EVM or Solana Mainnet, if mainnet is enabled A full list of all EVM or Solana providers that have been configured A convenience method that lets you retrieve a provider for a specific Chain ID Check out the reference for [EvmRpcProvider](/react-sdk/objects/EvmRpcProvider) and [SolanaRpcProvider](/react-sdk/objects/SolanaRpcProvider) ### Example Below is a simple example using EVM providers to fetch an arbitrary ENS mapping: ```TypeScript import { useRpcProviders } from '@dynamic-labs/sdk-react-core' import { evmProvidersSelector } from '@dynamic-labs/ethereum-core' const useLogEnsMapping = () => { const { defaultProvider } = useRpcProviders(evmProvidersSelector) const mainnetProvider = defaultProvider?.provider; const ensAddress = mainnetProvider.resolveName('myname.eth'); console.log('address for myname.eth', ensAddress); } ``` # Smart Wallet Chains If you are using our Zerodev integration to enable Smart Wallets, you'll need to already have the Ethereum chain enabled. If you don't, please refer to [this guide](/chains/enabling-chains). You will also need to install a new package, even if you already have `@dynamic-labs/ethereum` installed, it's called `ethereum-aa`. ```bash npm npm i @dynamic-labs/ethereum-aa ``` ```bash yarn npm i @dynamic-labs/ethereum-aa ``` Then, you need to add the `ZeroDevSmartWalletConnectors` to the `walletConnectors` array in the SDK settings: ```jsx import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'; import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'; import { ZeroDevSmartWalletConnectors } from '@dynamic-labs/ethereum-aa'; const App = () => ( ); ``` # Custom Information Capture ## Overview In order to capture information immediately after a user logs in that is not already available via our standard info capture (such as their shoe size, etc.), you can create custom fields to be prompted during onboarding and stored in the `metadata` object of the `user`. There are three different field types: ### Input * **Unique**: Can force uniqueness in the environment, ex: only one user can have the nickname `Bob`. * **Regex**: Can follow a regex, ex: text must be an Ethereum address: `^0x`. ### Dropdown * A list of options that a user can select in a dropdown, ex: `Pizza`, `Ice Cream`. ### Checkbox * Provide the text that goes along with a checkbox, ex: `Confirm that you are using this app at your own risk`. All of these fields can be configured to be optional, meaning they can be skipped during onboarding. Additionally, all fields can be edited by the user in the Dynamic Widget. ## Configuration In the Dynamic Dashboard, go to [the Login and User Profile Settings page](https://app.dynamic.xyz/dashboard/log-in-user-profile). Here, under "Additional User Information" you will see a list of your current available fields and at the bottom you will see a button to "Create New Field". # CSS Variables The Dynamic SDK allows you to customize the theme via [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties). We recommend setting these CSS variables in your host site by targetting the `dynamic-shadow-dom` class. Here is an example of a custom theme done via CSS variables and the code used below: EthereumWalletConnectors also includes all EVM compatible chains including layer 2's i.e. Base as well as [Dynamic Embedded Wallets](/wallets/embedded-wallets/dynamic-embedded-wallets). Learn more about WalletConnectors [here](/react-sdk/providers/dynamiccontextprovider#walletconnectors). ## Initialize the SDK ## Integration with `useOtpVerificationRequest` The `useUserUpdateRequest` hook is designed to work seamlessly with the [useOtpVerificationRequest](/react-sdk/hooks/useotpverificationrequest) hook. To handle email or SMS verification in another view or component, you can directly use the `useOtpVerificationRequest` hook, which provides the verifyOtp function. Using both hooks together ensures a streamlined user experience while maintaining security and data integrity. # useUserWallets Get access to the current user/session wallets Use this hook whenever you need access to all the current wallets in your app — it returns an array of wallets, with type `Wallet[]`. The array represents all wallets that were connected in the current session + all wallets authenticated by the current user. See [this section](#when-is-a-wallet-added-to-this-array) for more details. ### Example: listing which wallets are currently connected ```javascript import { FC } from 'react' import { useUserWallets } from '@dynamic-labs/sdk-react-core' export const ListConnectedWallets: FC = () => { const userWallets = useUserWallets() return (

Wallets

{userWallets.map((wallet) => (

{wallet.address}

))}
) } ``` ### What does the Wallet type look like? You can inspect the type using your code editor, but here's a summary: ```Typescript id: string; key: string; address: string; additionalAddresses: WalletAdditionalAddress[]; chain: string; isAuthenticated: boolean; connector: walletConnector ``` Find the reference for the `walletConnector` type [here](/wallets/using-wallets/interacting-with-wallets#walletconnector). ### When is a wallet added to this array? There are currently 2 ways a wallet can be added to the array: 1. When the a new wallet is connected to the current session. 2. When the user signs in, all wallets authenticated to his account are added. > Notice the intentional distinction between the *user* and the *current session*: if your end-user connects in `connect-only` mode, [he doesn't get a jwt](/wallets/advanced-wallets/connected-vs-authenticated#the-difference-in-practice). This means we have no access to the authenticated wallets. ### When is a wallet removed from this array? Wallets are only removed explicitly by the user, be it through log-out, unlinking, or disconnecting in `connect-only`. # useWalletConnectorEvent ### Summary The `useWalletConnectorEvent` hook is used for handling events from a `WalletConnector` or an array of `WalletConnectors`. This hook allows you to specify an event to listen to and a handler function that will be called whenever the event is emitted. The handler will receive the event arguments followed by the instance of the `WalletConnector` that emitted the event. | Parameter | Type | Description | | ------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | eventEmitters | WalletConnector or WalletConnector\[] | The WalletConnector instance(s) to attach the event listener to. If an array is provided, the event listener is attached to all provided connectors. | | eventName | string | The name of the event to listen for. | | handler | function | The callback function to execute when the event is emitted. The arguments to the callback are the arguments emitted with the event, followed by the WalletConnector instance that emitted the event. | ### Example Listen to primary wallet connector account changed ```tsx import { useWalletConnectorEvent, useDynamicContext } from '@dynamic-labs/sdk-react-core' const App = () => { const { primaryWallet } = useDynamicContext() useWalletConnectorEvent( primaryWallet?.connector, 'accountChange', ({ accounts }, connector) => { console.group('accountChange'); console.log('accounts', accounts); console.log('connector that emitted', connector); console.groupEnd(); }, ); return null; } ``` Listen to all wallets connectors for the disconnect event ```tsx import { useWalletConnectorEvent, useUserWallets } from '@dynamic-labs/sdk-react-core' const App = () => { const wallets = useUserWallets(); const walletsConnectors = wallets.map(({ connector }) => connector); useWalletConnectorEvent( walletsConnectors, 'disconnect', (connector) => { console.log(`Connector ${connector} disconnected`); } ); return null; } ``` # useWalletItemActions ### Summary A hook with utility functions to sign with a specific wallet. The hook needs to be initialized within a child of `DynamicContextProvier` #### `openWallet` - available from version `v0.14.32` Initiates the signing process for a specific wallet without opening the dynamic auth flow. For example, you can create a button that will sign the user with MetaMask specifically. ```TypeScript const SignWithMetaMaskButton = () => { const { openWallet } = useWalletItemActions(); return ( ) } ``` # useWalletOptions ### Summary The useWalletOptions hook allows you to start the process of connecting to a specific wallet. It provides a function to select a wallet by wallet key. Once this function is called, the connection process begins with the caveat that: * If you pass in a `walletKey` that supports multiple chains, such as `magiceden`, a user will first be asked to select which chain they want to connect with. Once a chain is selected, then the user will be prompted to connect. * If you pass in a `walletKey` that includes a chain, such as `magicedenbtc`, then the user will skip to the connection step. * If a wallet does not support multiple chains, such as `xverse`, then the user will simply go to the connection step. ### Usage Available props | Prop | Type | Description | | ------------------ | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | | selectWalletOption | `(walletKey: string) => Promise` | Function to select a specific wallet to connect with | | walletOptions | `Array<{isInstalledOnBrowser: boolean; key: string; name: string; group?: string}>` | List of avaiable wallet options with their keys, names and group (if defined) | ### Examples Example 1: Harcoded options ```tsx import { useWalletOptions } from "@dynamic-labs/sdk-react-core"; const WalletList = () => { const { selectWalletOption } = useWalletOptions(); const wallets = [ { key:'metamask', name: 'MetaMask' }, { key: 'magiceden', name: 'Magic Eden' } ]; return (
{wallets.map((wallet) => ( ))}
); }; ``` Example 2: Dynamically populated options ```tsx import { useWalletOptions } from "@dynamic-labs/sdk-react-core"; const WalletList = () => { const { selectWalletOption, walletOptions } = useWalletOptions(); const groupedWallets = walletOptions.reduce((options, wallet) => { const key = wallet.group || wallet.key; const name = wallet.groupName || wallet.name; if (!options[key]) { options[key] = name; } return options; }, {}); return (
{Object.entries(groupedWallets).map(([key, name]) => ( ))}
); }; ``` Example 3: Checking if a wallet is instaled in browser ```tsx import { useWalletOptions } from "@dynamic-labs/sdk-react-core"; const Main = () => { const { walletOptions } = useWalletOptions(); const isMagciEdenInstalled = walletOptions.find((wallet) => wallet.key === 'magiceden')?.isInstalledOnBrowser; return (
{isMagciEdenInstalled ? 'Magic Eden is installed' : 'Magic Eden is not installed'}
); }; ``` ### Hook Details **Function: selectWalletOption** The selectWalletOption function select a wallet to connect with. It takes a single argument, `walletKey`, which is the key of the wallet to connect with. You can dynamically find the available wallet keys in `walletOptions` or all the supported wallet keys either from [wallet-book](https://dynamic-static-assets.com/wallet-book/v1/latest/wallet-book.json) (object keys in groups or wallets) or in the [chains pages in the dashboard](https://app.dynamic.xyz/dashboard/chains-and-networks#evm). # SDK/User Loading States ## Overview Before using the SDK through hooks etc., you need to ensure that it has loaded. In addition, you might also want to wait for a user to have logged in to call certain hooks. This guide will show you how to check if the SDK has loaded and how to handle the different loading states for the login process. ## Wait for SDK to load (variable) The sdkHasLoaded variable is available from the [useDynamicContext](/react-sdk/hooks/usedynamiccontext) hook and can be used to check if the SDK has loaded. ```javascript import { useDynamicContext } from "@dynamic-labs/sdk-react-core"; const { sdkHasLoaded } = useDynamicContext(); sdkHasLoaded ? console.log("SDK has loaded") : console.log("SDK is still loading"); ``` ## Check if user is logged in (hook) The [useisloggedin hook](/react-sdk/hooks/useisloggedin) will tell you if the user has finished the whole onboarding process i.e. they signed in/up and completed any required [information capture](/users/information-capture). Note that Dynamic has two modes for a user to be in: connect-only and connect-and-sign (learn more [here](/wallets/advanced-wallets/connected-vs-authenticated)). In connect-only mode, the user is considered logged in once they have connected their wallet(s) and in connect-and-sign mode, the user is considered logged in once they have connected their wallet(s) and signed a message. useIsLoggedIn will return true for connect-only when a wallet is connected but there is no UserActivation, and for connect-and-sign when a wallet is connected and a valid user is present. ```jsx import { useIsLoggedIn } from '@dynamic-labs/sdk-react-core'; const MyComponent = () => { const isLoggedIn = useIsLoggedIn(); return (
{isLoggedIn ? (

You are logged in!

) : (

Please log in to continue.

)}
); }; export default MyComponent; ``` ## Check if user is authenticated but hasn't finished onboarding useIsLoggedIn tells you if the user has finished the whole onboarding process, but if you want to know if the user has authenticated but hasn't finished the process, you can use \[userWithMissingInfo] from the [useDynamicContext](/react-sdk/hooks/usedynamiccontext) hook. This will be undefined if the user is not authenticated or if they have finished the onboarding process and will contain the user object otherwise. Conversely, the user object from the same hook will be defined if the user is authenticated and has finished the onboarding process. ```jsx import { useDynamicContext, useIsLoggedIn } from '@dynamic-labs/sdk-react-core'; const MyComponent = () => { const isLoggedIn = useIsLoggedIn(); const { userWithMissingInfo } = useDynamicContext(); let message = ""; if (userWithMissingInfo) { message = "You are authenticated but need to complete the onboarding process."; } else if (!isLoggedIn) { message = "Please log in to continue."; } else { message = "You are logged in!"; } return (

{message}

); }; ``` ## Access user during login (handler) The [handleAuthenticatedUser handler](/react-sdk/handlers/handleauthenticateduser) is a handler that can be used to intercept the workflow once a user has been authenticated but before the auth process completes and we close the UI. ```jsx { console.log("handleBeforeAuth was called", args); await customUserObjectProcess(args.user); }, }, }} > {/* ... rest of your app ... */} ``` It gives you a [UserProfile](/react-sdk/objects/userprofile) object for the given user. ## Check when login has started (callback) The [onAuthInit](/react-sdk/events/onauthinit) callback gives you information about a login process that has just begun. ```jsx { console.log('onAuthInit was called', args); } } }} > {/* ... rest of your app ... */} ``` Check out [the full reference](/react-sdk/events/onauthinit) for the return value (args). ## Check when authentication has completed (callback) The [onAuthSuccess](/react-sdk/events/onauthsuccess) callback runs once the user has authenticated and is signed in (i.e. completed any mandatory info capture & MFA). ```jsx { console.log('onAuthSuccess was called', args); // you can get the jwt by calling the getAuthToken helper function const authToken = getAuthToken(); console.log('authToken', authToken); } } }} > {/* ... rest of your app ... */} ``` Check out [the full reference](/react-sdk/events/onauthsuccess) for the return value (args). ## Check if login failed (callback) There are two callbacks which you can use for this: 1. The [onAuthFailure](/react-sdk/events/onauthfailure) callback will be called when an authentication process fails, either by error or user closing the modal. 2. The [onAuthCancel](react-sdk/events/onauthflowcancel) callback will be called specifically if the modal is closed before login is completed, it is not called on error. # EvmRpcProvider An object representing a provider for a specific EVM chain. Exported by `@dynamic-labs/ethereum-core`. ```typescript import { Chain, PublicClient, Transport } from 'viem' type EvmRpcProvider = { chainId: number chainName: string provider: PublicClient } ``` # EvmRpcProviderMethods Methods and properties available to EVM rpc providers. Exported by `@dynamic-labs/ethereum-core`. ```typescript type EvmRpcProviderMethods = { defaultProvider: EvmRpcProvider | undefined providers: EvmRpcProvider[] | undefined getProviderByChainId: (chainId: number) => EvmRpcProvider | undefined } ``` Check out the reference for [EvmRpcProvider](/react-sdk/objects/EvmRpcProvider) # GenericNetwork An object representing a generic network, such as an EVM or Solana L2. Exported by `@dynamic-labs/sdk-api-core`. ```typescript type GenericNetwork = { blockExplorerUrls: Array chainId: number | string chainName?: string iconUrls: Array lcdUrl?: string name: string nameService?: NameService nativeCurrency: NativeCurrency networkId: number | string privateCustomerRpcUrls?: Array rpcUrls: Array vanityName?: string } ``` See also [NameService](/react-sdk/objects/NameService) and [NativeCurrency](/react-sdk/objects/NativeCurrency). The `lcdUrl` field is only required for Cosmos networks. # NameService An object representing a name service. Exported by `@dynamic-labs/sdk-api-core`. ```typescript type NameService = { registry?: string } ``` # NativeCurrency An object representing a name service. Exported by `@dynamic-labs/sdk-api-core`. ```typescript type NativeCurrency = { decimals: number denom?: string name: string symbol: string } ``` # SolanaRpcProvider An object representing a provider for a specific Solana chain. Exported by `@dynamic-labs/solana-core`. ```typescript import { Connection } from '@solana/web3.js' type SolanaRpcProvider = { chainId: string chainName: string provider: Connection } ``` # SolanaRpcProviderMethods Methods and properties available to Solana rpc providers. Exported by `@dynamic-labs/solana-core`. ```typescript type SolanaRpcProviderMethods = { defaultProvider: SolanaRpcProvider | undefined providers: SolanaRpcProvider[] | undefined getProviderByChainId: (chainId: string) => SolanaRpcProvider | undefined } ``` Check out the reference for [SolanaRpcProvider](/react-sdk/objects/SolanaRpcProvider) # AccessDeniedCustomButton An object containing custom text and action for access denied modal. | Field | Description | | :------------------- | :-------------------------------------------------------- | | title: string; | Defines the button's text. | | action?: () => void; | Defines the action of the button when click is triggered. | ## Usage ```Text TypeScript window.open('https://www.mywebsite.com/contact-us', '_blank'), title: 'Contact us', } }} > {/* ... rest of your app ... */} ``` # EvmNetwork Object which represents a network on the Ethereum Virtual Machine (EVM). It can be used in the [DynamicContextProvider](/react-sdk/providers/dynamiccontextprovider) or in the [DynamicWagmiConnector](/react-sdk/providers/dynamicwagmiconnector). ## Definition | Attribute | Value | Required/Optional | | ---------------------- | ---------------- | ----------------- | | blockExplorerUrls | `string[]` | Required | | chainId | `number` | Required | | name | `string` | Required | | iconUrls | `string[]` | Required | | nativeCurrency | `NativeCurrency` | Required | | networkId | `number` | Required | | privateCustomerRpcUrls | `string[]` | Optional | | rpcUrls | `string[]` | Required | | vanityName | `string` | Optional | ### NativeCurrency | Attribute | Value | Required/Optional | | --------- | -------- | ----------------- | | decimals | `number` | Required | | name | `string` | Required | | symbol | `string` | Required | | denom | `string` | Optional | ## Example Usage ```jsx const evmNetworks = [ { blockExplorerUrls: ['https://etherscan.io/'], chainId: 1, name: 'Ethereum Mainnet', iconUrls: ['https://app.dynamic.xyz/assets/networks/eth.svg'], nativeCurrency: { decimals: 18, name: 'Ether', symbol: 'ETH' }, networkId: 1, privateCustomerRpcUrls: ['https://mainnet.infura.io/v3/your-api-key'], rpcUrls: ['https://cloudflare-eth.com'], vanityName: 'Ethereum', }, ] return ( ... ) ``` # LocaleResource An object used with the locale prop on DynamicContextProvider, you can find a tutorial on how to use this type [here](/design-customizations/customizing-copy-translations). ## Properties The key of the object must be one of the following valid "lang"s: \| "ar" \| "da" \| "de" \| "en" \| "es" \| "fi" \| "fr" \| "he" \| "it" \| "ja" \| "nl" \| "pl" \| "pt" \| "ru" \| "uk" \| "zh" The value of the object must be a valid translation object - see below. ### Translations The translation object should follow the shape found in "@dynamic-labs/sdk-react-core/src/lib/locale/en/translation.js" which you can reach by going to the definition of LocaleResource in your IDE once imported (`import { LocaleResource } from '@dynamic-labs/sdk-react-core'`) Here is an example excerpt from that file: ```jsx dyn_account_exists: { connect: 'Connect with {{socialOauth}}', description: 'It looks like an account already exists using', title: 'Account already exists', trail_message_email: '. Please log in with your email.', trail_message_social: 'through {{socialOauth}}', }, ``` # PhoneData An object containing phone information required for sms verification. | Attribute | Type | Description | | :-------- | :------- | :-------------------------------------------------------------- | | dialCode | `string` | Country dial code (e.g: '1') | | iso2 | `string` | Country iso code (e.g: 'US') | | phone | `string` | Phone number, numbers only, without dial code (e.g: 5555555555) | # React Objects Introduction The SDK uses a number of objects to represent different things. Here is a list of all of the objects used by the SDK and links to their reference pages. [**AccessDeniedCustomButton**](/react-sdk/objects/access-denied-custom-button): An object containing custom text and action for access denied modal. [**EvmNetwork**](/react-sdk/objects/evmNetwork): Object which represents a network on the Ethereum Virtual Machine (EVM). [**Locale**](/react-sdk/objects/locale): Used within the locale prop of the [DynamicContextProvider](/react-sdk/providers/dynamiccontextprovider) to edit the copy displayed by the SDK [**JWT Payload**](/react-sdk/objects/user-payload): JWT to verify some claims about the end user. [**JwtVerifiedCredential**](/react-sdk/objects/verified-credential): A representation of a verified credential (Wallet, email, farcaster, phone, etc.). [**PhoneData**](/react-sdk/objects/phone-data): The phone information required for sms verification. [**SdkViews**](/react-sdk/objects/views): Used within the [DynamicContextProvider](/react-sdk/providers/dynamiccontextprovider) `overrides` prop to adapt the view shown to the user programmatically. **[UserProfile](/react-sdk/objects/userprofile)**: An object containing attributes about the user such as the wallet address, email, first name, etc. [**Wallet**](/react-sdk/objects/wallet): An object containing the attributes about the connected wallet. This object would be available immediately after a wallet has been connected. [**WalletsByChain**](/react-sdk/objects/wallets-by-chain): Array of objects, used primarily for bridging. [**WalletConnector**](/react-sdk/objects/walletconnector): This is Dynamic's abstraction over the wallet interface. This can be used to interact with the users wallet. # SocialProvider A union of all social provider names available for connection. Exported by `@dynamic-labs/client`. ```typescript type SocialProvider = | 'apple' | 'coinbaseSocial' | 'discord' | 'facebook' | 'farcaster' | 'github' | 'google' | 'telegram' | 'tiktok' | 'twitch' | 'twitter' ``` # JWT Payload When an end user connects their wallet, you, the developer, get a [JSON Web Token (JWT)](https://jwt.io/introduction) that can be used to verify some claims about the end user, notably a proof of ownership over a wallet public address. After authenticating the JWT token, see [Server-side verification](/authentication-methods/how-to-validate-users-on-the-backend), you may want to leverage user and wallet information provided in the JWT. Below we have the content defined with the aim of following the JWT standards. ##### Standard JWT claims: See: [https://www.rfc-editor.org/rfc/rfc7519#section-4.1](https://www.rfc-editor.org/rfc/rfc7519#section-4.1) | Field | Description | | ----- | --------------------------------------------------------------------------------------------- | | aud | Audience for the JWT token. This claim shows what domain of the indended audience of the JWT. | | iss | Issuer of the JWT token. This claim shows app.dynamic.xyz generated and issued the JWT. | | sub | Subject of the JWT token. userId in the deprecated info claim. | | iat | Timestamp when the JWT token was issued. | | exp | Timestamp when the JWT token will expire. | ##### Dynamic-specific claims: These fields are **optional** and you depends on whether you want to collect this information during onboarding. For more information about collecting this information, see [here](/users/information-capture). | alias | Alias field from customer information capture. | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | email | Email field from customer information capture. | | environment\_id | Unique ID of the project environment for the SDK, from [https://app.dynamic.xyz/dashboard/api](https://app.dynamic.xyz/dashboard/api). environmentId in the deprecated info claim. | | given\_name | First name field from customer information capture. firstName in the deprecated info claim. | | family\_name | Last name field from customer information capture. lastName in the deprecated info claim. | | lists | Names of access lists enabled for this user. | | verified\_credentials | List of all [verified credentials](/react-sdk/objects/verified-credential) connected to this user. | | verified\_account | If present, this was the most recently signed and verified account. | #### Example ```JSON{ "alias": "john", "aud": "https://dashboard.hello.xyz", "verified_credentials": [ { "address": "0x000123abc", "chain": "eip155", "id": "af615228-99e5-48ee-905d-4575f0a6bfc9", "wallet_name": "metamask" } ], "email": "[[email protected]](/cdn-cgi/l/email-protection)", "environment_id": "fb6dd9d1-09f5-43c3-8a8c-eab6e44c37f9", "family_name": "bot", "given_name": "jon", "iss": "app.dynamic.xyz/fb6dd9d1-09f5-43c3-8a8c-eab6e44c37f9", "lists": [ "Community dashboard acess list" ], "sub": "d261ee91-8ea0-4949-b8bb-b6ab4f712a49", "verified_account": { "address": "0x000123abc", "chain": "eip155", "id": "af615228-99e5-48ee-905d-4575f0a6bfc9", "wallet_name": "metamask" }, "iat": 1660677597, "exp": 1660684797 } ``` # UserProfile An object containing attributes about the user such as id, email, first name, etc. | Field | Description | | ---------------------------------------------------------------------------------------- | ----------------------------------------------------- | | userId?: string | \[Optional] - Dynamic's UUID | | sessionId: string | \[Optional] - The current session ID | | environmentId?: string | \[Optional] - Dynamic environment ID | | newUser?: boolean | \[Optional] - Is it first time user created/logged in | | email?: string | \[Optional] - User's email | | alias?: string | \[Optional] - User's alias | | firstName?: string | \[Optional] - User's first name | | lastName?: string | \[Optional] - User's last name | | phoneNumber? string | \[Optional] - User's phone number | | lists?: string\[] | \[Optional] - User's access lists | | verifiedCredentials?: [JWTVerifiedCredential](/react-sdk/objects/verified-credential)\[] | \[Optional] - User's verified credentials | | lastVerifiedCredentialId: string \|\ undefined | \[Optional] - User's last verified credential ID | | scope?: string | \[Optional] - User's scope | # JwtVerifiedCredential | Field | Description | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | id: string | internal ID for this VC | | address?: string | \[Optional] - wallet address associated with the VC | | chain?: string | \[Optional] - chain associated with the VC | | refId?: string | \[Optional] - if using oauth, this is the embedded wallet\_id associated with the social account | | signerRefId?: boolean | \[Optional] - for smart contract wallets, signerRefId is the wallet ID of the signer for this SCW | | email?: string | \[Optional] - email associated with the VC | | nameService?: NameServiceData | \[Optional] - ens data name and avatar url, if one is associated with the wallet in the VC, see [NameServiceData](/react-sdk/objects/verified-credential#nameservicedata) below for more details | | publicIdentifier?: string | \[Optional] - common way to reference the VC. i.e. email address for email VCs, name of user for Google VC | | walletName?: string | \[Optional] - wallet name associated with the VC | | walletProvider?: WalletProviderEnum | \[Optional] - type of wallet, see [WalletProviderEnum](/react-sdk/objects/verified-credential#walletproviderenum) below for more details | | walletProperties?: WalletProperties | \[Optional] - generally only used for embedded wallets with Turnkey, see [WalletProperties](http://localhost:3000/react-sdk/objects/verified-credential#walletproperties) below for more details | | format: JwtVerifiedCredentialFormatEnum | \[Optional] - the type of VC i.e. email, see [JwtVerifiedCredentialFormatEnum](/react-sdk/objects/verified-credential#jwtverifiedcredentialformatenum) below for more details | | oauthProvider?: SocialSignInProviderEnum | \[Optional] - the social provider associated with the VC i.e. apple, see [ProviderEnum](/react-sdk/objects/verified-credential#providerenum) below for more details | | oauthUsername?: string | \[Optional] - username associated with the social provider for the VC | | oauthDisplayName?: string | \[Optional] - display name associated with the social provider for the VC | | oauthAccountId?: string | \[Optional] - ID associated with the social provider for the VC | | oauthAccountPhotos?: Array\ | \[Optional] - photos associated with the social provider for the VC | | oauthEmails?: string | \[Optional] - emails associated with the social provider for the VC | | previousUsers?: Array\ | \[Optional] - user IDs who were previously associated with the VC | | embeddedWalletId?: string \| null | \[Optional] - ID of the embedded wallet associated with the VC | ## NameServiceData | Field | Description | | --------------- | -------------------------------------------- | | avatar?: string | \[Optional] - avatar associated with the ens | | name?: string | \[Optional] - name associated with the ens | ## WalletProviderEnum 'browserExtension' || 'custodialService' || 'walletConnect' || 'qrCode' || 'deepLink' || 'embeddedWallet' || 'smartContractWallet' ## WalletProperties | Field | Description | | --------------------------------- | ------------------------------------------------------------------ | | turnkeySubOrganizationId?: string | \[Optional] - turnkey sub organization ID associated with wallet | | turnkeyHDWalletId?: string | \[Optional] - turnkey HD wallet ID associated with the the wallet | | isAuthenticatorAttached?: boolean | \[Optional] - is authenticator i.e. passkey attached to the wallet | ## JwtVerifiedCredentialFormatEnum 'blockchain' || 'email' || 'oauth' || 'passkey' ## ProviderEnum 'emailOnly' || 'magicLink' || 'apple' || 'bitbucket' || 'discord' || 'facebook' || 'github' || 'gitlab' || 'google' || 'instagram' || 'linkedin' || 'microsoft' || 'twitch' || 'twitter' || 'blocto' || 'banxa' || 'dynamic' || 'alchemy' || 'zerodev' || 'turnkey' # SdkViews Views are a new feature as of SDK V0.19, please be aware there may be breaking changes in the future. ## What is it? Views are used to customize the kind of UI that shows up at any point in time in your application. ## How does it work? Views are used primarily in the overrides prop of the [DynamicContextProvider](/react-sdk/providers/dynamiccontextprovider). You pass in an array of configurations for each view you want to customize, each view has its own set of options. ## Supported views: * [Login](/react-sdk/objects/views#login-view) * [Wallet List](/react-sdk/objects/views#wallet-list) ## Login View The `SdkViewType.Login` is used to adjust the login/signup UI options programmatically. When using the login view, you add an object to the views array. This object should have `type: SdkViewType.Login` and `sections` which is an array of SdkViewSection objects. Please read [here](/design-customizations/views#types-of-views) for a comprehensive guide on using this feature. ## Wallet List The `wallet-list` configuration enables you to define tabs with predetermined labels, icons, filters, and recommended wallets, enhancing your application's wallet selection interface. This feature is particularly useful for grouping wallets. Available from version 2.0.0+ #### Configuring Wallet List Tabs In the `DynamicContextProvider` setup, the `overrides` field is used to configure each tab in the wallet list. The configuration options available for each tab allow for detailed customization: * **Label and Icon**: Customize the tab's appearance with a `label` for text and an `icon` for visual representation. The `icon` can be one of the following options: * A icon from the dynamic iconic package ```tsx import { BitcoinIcon } from '@dynamic-labs/iconic'; } ] } } ] } }} /> ``` * A image URL ```tsx ``` * Or you can bring your own React icon ```tsx } ] } } ] } }} /> ``` * **Wallets Filter**: This option enables to dynamic display of wallets based on the selected tab. Clients have the flexibility to write custom filter functions or utilize predefined ones, for more information read the [sort and filter wallets](/wallets/advanced-wallets/sort-and-filter-wallets) doc * **Recommended Wallets**: Specify recommended wallets for each tab by providing [wallet option](/react-sdk/objects/wallet-option) keys and optional labels. This feature is designed to highlight preferred wallets, steering users towards secure and suitable options for their specific needs. * **Style**: An optional field that determines how the tabs are displayed within the wallet list. Currently, the only supported style is `"grid"`. #### Example Configuration Below is an example showcasing the setup for tabs that categorize wallets by blockchain network, utilizing both custom and predefined filter functions: ```tsx import { DynamicContextProvider, FilterChain } from '@dynamic-labs/sdk-react-core' import { BitcoinIcon, EthereumIcon, FlowIcon, SolanaIcon, } from '@dynamic-labs/iconic'; const App = () => { return ( }, walletsFilter: FilterChain('EVM'), recommendedWallets: [ { walletKey: 'phantomevm', }, ], }, { label: { icon: }, walletsFilter: FilterChain('SOL'), }, { label: { icon: }, walletsFilter: FilterChain('BTC'), }, { label: { icon: }, walletsFilter: FilterChain('FLOW'), }, ] } } ] } }} > ) } ``` This is the wallet list view with the tabs | All chains tab selected | Ethereum selected | | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | | | # Wallet An object containing the attributes about the user wallets. ### Props | Field | Description | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | additionalAddresses: WalletAdditionalAddress\[] | Additional addresses associated to the wallet (e.g. ordinals and payment addresses for bitcoin wallets) | | address: string | Public address of the connected wallet | | chain: string | Current BlockChain name (e.g: 'ETH', 'SOL', 'BTC', etc) | | connector: WalletConnector | The wallet connector object | | id: string | The wallet's unique id (matches thw wallet verified credential on connect-anf-sign) | | isAuthenticated: boolean | True if the user is authenticated, otherwise it's false | | key: string | The wallet key (e.g. metamask, phantom, etc) | ### Methods | Method | Description | | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | getBalance(): Promise\ | Retrieves the balance of the wallet. | | getNameService(): Promise\ | Retrieves the name service data associated with the wallet. | | isConnected(): Promise\ | If the wallet is connected. | | proveOwnership(messageToSign: string): Promise\ | Proves ownership of the wallet by signing a message. | | signMessage(messageToSign: string): Promise\ | Signs a message using the wallet. | | switchNetwork(networkChainId: number \| string): Promise\ | Switches the network that the wallet is connected to. | | sync(): Promise\ | Prompts the user to reconnect the wallet if not connected and only resolves when the wallet is connected and active. | # WalletOption A WalletOption type is used to represent a wallet option in the wallet selection modal. This is as opposed to a [Wallet](/react-sdk/objects/wallet) type, which is used to represent a wallet that is currently connected. | Field | Optional/Required | Type | Description | | -------------------- | ----------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | isInstalledOnBrowser | | boolean | Is this wallet installed via a browser extension | | key | | string | Normalization of the wallet name | | name | | string | The name of the given wallet | | walletConnector | | [WalletConnector](/react-sdk/objects/walletconnector) | The wallet connector interface for the given wallet | | group | Optional | string | The wallet which can connect to multiple chains, not present if the wallet is not multi-chain compatible, or if multiple chains are not enabled | | groupedWallets | Optional | WalletOption\[] | Where a wallet supports multiple chains, this array contains t | ## Example ```jsx isInstalledOnBrowser: true; key: 'phantom'; name: 'Phantom'; walletConnector: WalletConnector; group: 'phantom'; groupedWallets: [ { isInstalledOnBrowser: true; key: ''; name: 'phantom EVM'; walletConnector: WalletConnector; }, { isInstalledOnBrowser: true; key: ''; name: 'phantom Solana'; walletConnector: WalletConnector; }, { isInstalledOnBrowser: true; key: ''; name: 'phantom Ledger'; walletConnector: WalletConnector; }, ]; ``` # WalletConnectConnector This is Dynamic's WalletConnect connector over the basic wallet interface. This can be used to interact with the users WalletConnect wallets. It has all methods available in the [WalletConnector](https://docs.dynamic.xyz/react-sdk/objects/walletconnector) and some additional method specific to WalletConnect wallets. IWalletConnectConnector is available in SDK v2.0.0+. | Field | Description | | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | getSupportedNetworks: Promise\ | A method to retrieve the supported/approved networks for the WalletConnect wallet. Some wallets will only allow approve a network if the user manually switches in the wallet app first. | ## Interface definition ```ts interface IWalletConnectConnector { getSupportedNetworks: Promise }; ``` ### How to use it In this example, we are going to return all supported networks for the wallet connector. ```JavaScript import { useDynamicContext } from '@dynamic-labs/sdk-react-core'; import { isWalletConnectConnector } from '@dynamic-labs/wallet-connector-core'; const MyComponent = () => { const { primaryWallet } = useDynamicContext(); const getWCSupportedNetworks = async () => { if (!isWalletConnectConnector(primaryWallet?.connector)) { return; } const supportedNetworks = await primaryWallet.connector.getSupportedNetworks(); console.log('supportedNetworks', supportedNetworks); return supportedNetworks; }; ... }; ``` # WalletConnector This is Dynamic's abstraction over the wallet interface. This can be used to interact with the users wallet. | Field | Description | | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | fetchPublicAddress: Promise\ | A method to fetch the public address (alternatively the address could be fetched from useDynamicContext's user object) | | getPublicClient(): Viem Public Client \| undefined | The provider should be used for read only actions on the block chain.Ethereum - A [Viem Public Client](https://viem.sh/docs/clients/public.html) SOLANA -[solana/web3js.Connection](https://solana-labs.github.io/solana-web3.js/classes/Connection.html) | | getWalletClient() : Promise\\\ | Representation of the signer (the wallet) for actions that require signatures with the private key.Ethereum - [Viem Wallet Client](https://viem.sh/docs/clients/wallet.html), Solana - The active wallet | | name: string | The wallet name | | signMessage(messageToSign: string): Promise\ | A method to sign a message | | supportedChains: Chain\[] | The chains that the wallet supports | | getDeepLink(): string | A method to get a deep link to a wallet for mobile | | getAccountAbstraction(): Smart Wallet Provider | A method to get the smart wallet provider for more advanced usage | | supportsNetworkSwitching(): boolean | Whether the connector supports network switching. | | switchNetwork(\{ networkChainId, networkName }: \{ networkChainId?: number; networkName?: string; }): Promise\ | Switch to another network by provider either the network name or chain id specified in the list of EvmNetwork | # WalletsByChain ## Description An Array of objects, in which each object contains the chain name to be connected for the chain. Primarily used for [bridging](/building-bridges/dynamic-bridge-widget) purposes. | Field | Description | | ------------- | ----------- | | chain: string | Chain name | ## Example ```jsx [ { chain: "EVM", }, { chain: "STARK", }, ]; ``` # Introduction to the SDK The SDK allows you to build authentication and authorization into your application in a few lines of code. ## Getting Started We provider step by step guides on getting started with the SDK [here](/adding-dynamic/adding-the-sdk). You'll also want to check out the [UI components customization guides](/ui-components), or [the headless guides](/headless/headless-overview) if you need to use your own UI components. Below we'll introduce you to the main parts of the SDK and how they can be used. ## Main Concepts ### Loading States [Our Loading/Login States guide](/react-sdk/loading-login-states) show you how do everything from wait for the SDK to be loaded to checking if a user is authenticated. ### Components [Components](/react-sdk/components/components-introduction) exist as three main types: 1. UI components (create UI for different parts of the onboarding flow) 2. Context providers (wrap your app in a React context to access SDK functionality) 3. Connectors (help integrate different parts of the SDK i.e. Wagmi or specific chains) ### Handlers [Handlers](/react-sdk/handlers/handlers-introduction) are a way to programmatically customize synchronous behaviors of the SDK (i.e. run a blocking fraud check during wallet connection). ### Events [Events](/react-sdk/events/events-introduction) are a way to listen for SDK events and run your own asynchronous code at certain points. ### Hooks [Dynamic hooks](/react-sdk/hooks/hooks-introduction) are custom React hooks that allow you to access SDK functionality in your React components. ### Utilities [Utilities](/react-sdk/utilities/utilities-introduction) are functions that allow you to do certain tasks in your application quickly i.e. check the network of a wallet. # DynamicContextProvider ## Settings Passed in using the "settings" prop, available when you first initialize `DynamicContextProvider` in your App. ### accessDeniedMessagePrimary **Type:** `string` **Description:** Custom main error message used when a wallet attempts to authenticate via Dynamic and is rejected because it does not have access. Defaults to "Access denied" ### accessDeniedMessageSecondary **Type:** `string` **Description:** Custom secondary error message used when a wallet attempts to authenticate via Dynamic and is rejected because it does not have access. Defaults to "We couldn't find your wallet address on our access list of customers." ### accessDeniedButton **Type:** `AccessDeniedCustomButton` **Description:** Custom secondary error button text and action when a wallet attempts to authenticate via Dynamic and is rejected because it does not have access. Defaults to "Try another method" and allow user to choose another login option. Please see: [AccessDeniedCustomButton](/react-sdk/objects/access-denied-custom-button) ### coinbaseWalletPreference **Type:** `'all' | 'smartWalletOnly' | 'eoaOnly'` **Description:** Determines which connection options users will see. Defaults to all. Please see: [https://www.smartwallet.dev/sdk/makeWeb3Provider#options-optional](https://www.smartwallet.dev/sdk/makeWeb3Provider#options-optional) ### cssOverrides **Type:** `string | JSX.Element` **Description:** Allows for custom CSS overrides via ShadowDom. Please see: [Custom CSS](/design-customizations/css/custom-css)] ### debugError **Type:** `boolean` **Description:** When enabled, errors caught during the authentication step and their stack trace will be set in a state and displayed in the front end. ### deepLinkPreference **Type:** `'native' | 'universal'` **Description:** Controls the type of deep link used when connecting a mobile wallet. Defaults to 'native'. This is useful for example if your app is running in a webview of a native mobile app, and you want to be able to link out to any wallet without having to modify your iOS build config. In this case, you can set this to 'universal'. ### displaySiweStatement **Type:** `boolean` **Description:** When enabled, this will show a message on terms of service and privacy policy in the signing message on the authentication step. ### enableVisitTrackingOnConnectOnly **Type:** `boolean` **Description:** When the Dynamic SDK is being used with auth mode = connect-only, we require this to be set to "true" to track visits of connected wallets in this environment. ### environmentId **Type:** `string` **Description:** You will need to specify your app's environment ID, which refers to a unique environment and its settings in Dynamic. To get your environment ID, go to [dashboard's API tab](https://app.dynamic.xyz/dashboard/api) ### events **Type:** `DynamicEvents` **Description:** This prop allows custom event callbacks after important events during the authentication flows for Dynamic's React SDK. For more information, please see [the main React SDK reference](/react-sdk) ### initialAuthenticationMode **Type:** `AuthModeType` **Description:** Sets the initial SDK authentication mode to either connect-only or connect-and-sign. connect-only does not require users to authenticate to prove ownership of their wallet. connect-and-sign will require an additional step for users to prove ownership of their wallet. Defaults to connect-and-sign. See also the [setAuthMode](/react-sdk/hooks/usedynamiccontext) method, which allows you to toggle this after the app has loaded. ### logLevel **Type:** `keyof typeof LogLevel` **Description:** The log level to use for client side logging with our SDK. Defaults to WARN ### mobileExperience **Type:** `'in-app-browser' | 'redirect'` **Description:** This setting determines how users connect on mobile devices. By default, it is set to 'in-app-browser', which means the connection will open within the wallet's in-app browser. If you prefer to have users connect via WalletConnect, set this option to 'redirect'. This will prompt users to accept connection requests in their wallet app and, for Phantom users, automatically redirect them back to their mobile browser. [See here for examples](#setting-mobile-experience) ### newToWeb3WalletChainMap **Type:** `ChainToWalletMap` **Description:** When provided, this is used in the Get your first wallet view in the wallet list modal. This can be helpful to steer initial customers who do not have a wallet to download and use a specific chain and wallet. ### networkValidationMode **Type:** `'always' | 'sign-in' | 'never'` **Description:** Note: Supported only in connect-only. Defines how the Dynamic SDK will enforce the wallet network. * **always** - requires the wallet to be on an enabled network while connecting and while the session is active * **sign-in** - will only enforce the network on connect * **never** - completely turn off the network validation. Defaults to `sign-in`. ### onboardingImageUrl **Type:** `string` **Description:** When provided, this image will be shown during the customer information capture step after a wallet successfully authenticates with Dynamic and the environment requires additional information from the user. ### policiesConsentInnerComponent **Type:** `ReactNode | ReactNode[]` **Description:** For environments with the username setting enabled, you will need to pass in a value for this prop to show a custom prompt or label for the policies contest checkboxes displayed during customer information capture after signing. ### privacyPolicyUrl **Type:** `string` **Description:** When provided, this will display a privacy policy URL on the signing step. This should be set to a URL of your organization's privacy policy web page. ### recommendedWallets **Type:** `RecommendedWallet[]` **Description:** Available from V1.2 only. An array of wallet keys that will be recommended to the user. See more in [our section on recommending wallets](/wallets/advanced-wallets/recommend-wallets). ### redirectUrl **Type:** `string` **Description:** When provided, this will redirect the user to the specified URL after the user has successfully gone through an oauth flow (social login or social account linking). ### shadowDOMEnabled **Type:** `boolean` **Description:** Shadow DOM allows the SDK to look as intended wherever it is hosted and it plays nicely with your existing styling system. For more information, please see: [Custom CSS](/design-customizations/css/custom-css) ### siweStatement **Type:** `string` **Description:** When provided, this custom message will be shown on the message to sign for the wallet signing step. ### termsOfServiceUrl **Type:** `string` **Description:** When provided, this will display a terms of service URL on the signing step. This should be set to a URL of your organization's terms of service web page. ### walletConnectors **Type:** `[]walletConnector` **Description:** When provided, will enable whatever connectors you pass so that your end user can signup/login using those wallets. For the list of available connectors, see the walletConnectors section below. ### walletConnectPreferredChains **Type:** Not specified **Description:** Relevant to Wallet Connect only, used to determine which chains to establish a connection with first. The value must be an array containing [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) chain ID's. The format for this is `{namespace-goes-here}:{reference-goes-here}`. Currently we only support Ethereum, so it will always be `eip155:{reference-goes-here}`. For example, Ethereum mainnet being \['eip155:1'] ### walletsFilter **Type:** `(options: WalletOption[]) => WalletOption[]` **Description:** When specified, this is a custom function that allows clients of Dynamic SDK to filter out wallet options based on a function on the wallet options. For example: `walletsFilter: (wallets) => wallets.filter((w) => w.key !== 'walletx')` will exclude walletx from showing up on the wallet list. ### bridgeChains **Type:** `WalletsByChain` **Description:** (Only use with bridging) Which chains should be used for bridging. ### socialProvidersFilter **Type:** `(providers: SocialOAuthProvider[]) => SocialOAuthProvider[]` **Description:** When specified, this is a custom function that allows clients of Dynamic SDK using social auth to filter or modify the order of the social options displayed to the user. For example, we can only show github oauth option: `socialProvidersFilter: (providers) => (['github'])`. ### overrides **Type:** `{ views: SdkView[], evmNetworks: EvmNetwork[] }` **Description:** Used for passing in [Views](/react-sdk/objects/views) or [evmNetworks](/chains/network-switching#evmnetworks). ### enableConnectOnlyFallback **Type:** `boolean` **Description:** When `true`, enables the SDK to fallback to wallet connect-only auth mode if connection to Dynamic's servers is not possible. Available in version 1.1 and above ### defaultPhoneInputIso2 **Type:** `string` **Description:** Used to define which phone number country code should be used as the default in all phone inputs, ex: `defaultPhoneInputIso2: "fr"` ### social **Type:** `{ strategy: 'redirect' | 'popup' }` **Description:** Allow to customize the default social behavior from 'redirect' to 'popup' ## walletConnectors Here are the possible options for the walletConnectors array. For each one, you must make sure you have installed the package first: Please note that @dynamic-labs/ethereum (EthereumWalletConnectors) contains all EVM chains, not just Ethereum. It also includes Dynamic-powered embedded wallets, as these are EVM based too. | Package Name | Chain | WalletConnector to include | | :--------------------- | :----- | -------------------------- | | @dynamic-labs/ethereum | EVM | `EthereumWalletConnectors` | | @dynamic-labs/algorand | ALGO | `AlgorandWalletConnectors` | | @dynamic-labs/solana | SOL | `SolanaWalletConnectors` | | @dynamic-labs/flow | FLOW | `FlowWalletConnectors` | | @dynamic-labs/starknet | STARK | `StarknetWalletConnectors` | | @dynamic-labs/cosmos | COSMOS | `CosmosWalletConnectors` | ##### EVM Addon Wallets | Package Name | Which Wallets | WalletConnector to include | | :------------------- | :------------ | :-------------------------- | | @dynamic-labs/magic | *magic* | `MagicWalletConnectors` | | @dynamic-labs/blocto | *blocto* | `BloctoEvmWalletConnectors` | ## Locale This prop is for editing copy and adding translations to the SDK. For more information, please see [the customizing copy guide](/design-customizations/customizing-copy-translations) and [reference](/react-sdk/objects/locale). ## Examples #### Initiate Dynamic using only defaults ```JavaScript ``` #### Initiate Dynamic with Ethereum and Starknet wallets enabled ```JavaScript import { EthereumWalletConnectors } from "@dynamic-labs/ethereum"; import { StarknetWalletConnectors } from "@dynamic-labs/starknet"; ``` #### Initiate Dynamic using all available methods ```JavaScript { console.log('in onAuthFlowClose'); }, onAuthFlowOpen: () => { console.log('in onAuthFlowOpen'); }, onAuthSuccess: () => { navigate('/dashboard/overview'); }, onLogout: () => { console.log('in onLogout'); }, }, initialAuthenticationMode: 'connect-only', logLevel: 'DEBUG', newToWeb3WalletChainMap: { 1: ['metamask', 'walletconnect'], 137: ['metamask', 'walletconnect'], 56: ['metamask', 'walletconnect'], 80001: ['metamask', 'walletconnect'], }, onboardingImageUrl: 'https://i.imgur.com/3g7nmJC.png', policiesConsentInnerComponent: (

By clicking "Connect", you agree to our{' '} Terms of Service {' '} and{' '} Privacy Policy .

), privacyPolicyUrl: 'https://www.dynamic.xyz/privacy-policy', shadowDOMEnabled: true, siweStatement: 'Custom message to sign', termsOfServiceUrl: 'https://www.dynamic.xyz/terms-of-service', walletsFilter: (wallets) => wallets.filter((w) => w.key !== 'walletx'), }}>
``` #### Do not show `walletx` on the wallet list ```JavaScript >' walletsFilter: (wallets) => wallets.filter((w) => w.key !== 'walletx'), }} > ``` #### With events callbacks ```JavaScript >', events: { onAuthFlowClose: () => { console.log('in onAuthFlowClose'); }, onAuthFlowOpen: () => { console.log('in onAuthFlowOpen'); }, onAuthSuccess: () => { navigate('/dashboard/overview'); }, onLogout: () => { console.log('in onLogout'); }, }, }}> ``` #### Setting mobile experience ##### Globally for all wallets ```JavaScript >', mobileExperience: 'redirect' | 'in-app-browser' }}> ``` ##### On a wallet by wallet basis with optional default for all non-specified wallets **Note**: The walletKey can be found on the chains and networks page of the dashboard [here](https://app.dynamic.xyz/dashboard/chains-and-networks#evm) ```JavaScript >', mobileExperience: { '<>': 'redirect' | 'in-app-browser', default: 'in-app-browser' } }}> ``` # DynamicWagmiConnector The `DynamicWagmiConnector` component integrates your Dynamic project settings with Wagmi # Usage ```typescript import { DynamicWagmiConnector } from "@dynamic-labs/wagmi-connector"; import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core"; function App() { return ( ); } ``` # Props ## evmNetworks You can pass a static `evmNetworks` array. This will be passed down to the [Wagmi client config](https://wagmi.sh/react/client#configuration). The reference for an EvmNetwork can be found [here](/react-sdk/objects/evmNetwork). Example: ```typescript const evmNetworks: EvmNetwork[] = [ { blockExplorerUrls: ["https://etherscan.io/"], chainId: 1, chainName: "Ethereum Mainnet", iconUrls: ["https://app.dynamic.xyz/assets/networks/eth.svg"], nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" }, networkId: 1, privateCustomerRpcUrls: ["https://mainnet.infura.io/v3/your-api-key"], rpcUrls: ["https://cloudflare-eth.com"], vanityName: "Ethereum", }, ]; ``` ### WebSocket For webSocket support with Wagmi, you can pass an object as the privateCustomerRpcUrls with your webSocket url configuration ```typescript const evmNetworks: EvmNetwork[] = [ { ... privateCustomerRpcUrls: [ { url: "https://mainnet.infura.io/v3/your-api-key", webSocket: "wss://mainnet.infura.io/v3/your-api-key" } ], ... }, ]; ``` # Providers and Connectors Introduction You can see the full UI implemented at any time in our demo environment: [https://demo.dynamic.xyz](https://demo.dynamic.xyz) #### Dynamic Context Provider The [**DynamicContextProvider**](/react-sdk/providers/dynamiccontextprovider) is a provider component provides the context for the rest of the components to work. It must wrap all Dynamic related components of your application. #### Dynamic Wagmi Connector The [**DynamicWagmiConnnector**](/react-sdk/providers/dynamicwagmiconnector) is responsible for helping your Dynamic application to integrate with Wagmi out of the box. # Upgrade from V0 to V1 ## From V0.19 to V1 This upgrade guide is specific to implementing the SDK itself. ### Breaking Changes #### userWallets hooks * connectedWallets , secondaryWallets and linkedWallets all been removed in favor of userWallets hook. See [here](/react-sdk/hooks/useuserwallets) for more info. ```jsx import { useDynamicContext, getNetwork } from '@dynamic-labs/sdk-react-core'; const App = () => { const { connectedWallets } = useDynamicContext(); useEffect(() => { connectedWallets.forEach(async ({ connector }) => { const network = await getNetwork(connector); ... }); }, [connectedWallets]); ... } ``` ```jsx import { useUserWallets, getNetwork } from '@dynamic-labs/sdk-react-core'; const App = () => { const userWallets = useUserWallets(); useEffect(() => { userWallets.forEach(async ({ connector }) => { const network = await getNetwork(connector); ... }); }, [userWallets]); ... } ``` #### EthereumSmartWalletConnectors -> ZeroDevSmartWalletConnectors * (v1 alpha -> v1) EthereumSmartWalletConnectors is now renamed to ZeroDevSmartWalletConnectors. You use this connector when you want to use AA wallets. ```jsx import {DynamicContextProvider} from "@dynamic-labs/sdk-react-core"; import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'; import { ZeroDevSmartWalletConnectors } from '@dynamic-labs/ethereum-aa'; const App = () => ( ); export default App; ``` ```jsx import {DynamicContextProvider} from "@dynamic-labs/sdk-react-core"; import { EthereumWalletConnectors } from "@dynamic-labs/ethereum"; import { EthereumSmartWalletConnectors } from "@dynamic-labs/ethereum-aa"; const App = () => ( ); export default App; ``` #### wallets -> walletConnectorOptions * Wallets property returned by useDynamicContext now renamed to walletConnectorOptions `````jsx import { useDynamicContext } from "@dynamic-labs/sdk-react-core"; const App = () => { const { walletConnectorOptions } = useDynamicContext(); return (
{walletConnectorOptions.map((wallet) => (
{wallet.name}
))}
); }; export default App ;````
```jsx import { useDynamicContext } from "@dynamic-labs/sdk-react-core"; const App = () => { const { wallets } = useDynamicContext(); return (
{wallets.map((wallet) => (
{wallet.name}
))}
); }; export default App; `````
#### walletsByChain -> bridgeChains * walletsByChain has been renamed to bridgeChains ```jsx import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core"; const App = () => { return ( ); }; export default App; ``` ```jsx import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core"; const App = () => { return ( ); }; export default App; ``` ### Non Breaking Changes * Turnkey wallets are now created as Turnkey HD wallets. ### New Features * eip6963 is now fully supported without any need for changes on your end! * Listening to changes in wallet connectors is now supported via a hook called useWalletConnectorEvent. See [here](/react-sdk/hooks/usewalletconnectorevent) for more info. * You can now trigger the onramp flow programmatically using the useFunding hook. See [here](/react-sdk/hooks/usefunding) for more info. * Support for account recovery via a hook has been added. See [here](/react-sdk/hooks/usepasskeyrecovery) for more info. * We now generate HD wallets by default, there is nothing you need to do to take advantage of this. * You can now generate smart contract wallets (SCWs) using our Smart Wallet integrations. See [here](/smart-wallets/add-smart-wallets) for more info. * All of the copy which is used in the UI from the SDK is now completely editable. See [here](/design-customizations/customizing-copy-translations) for more info. * You can control what kind of signup/login options are shown in your UI on a programmatic basis regardless of what is enabled in the dashboard. See [here](/design-customizations/views) for more info. * Embedded wallets has been split up into the generation step and the claim step which means you can now give a user a wallet but without them adding a passkey until they make their first transaction. * Along the same lines as above, you can also pregenerate a wallet for a user without any interaction from them by using our API directly. See [here](/api-reference/endpoints/wallets/createWallet) for more info. * Webhooks are now offered out of the box! You do not need to make any SDK changes to take advantage of this. See [here](/developer-dashboard/webhooks) for more info. ## From V0.18 to V0.19 ### *Summary* This upgrade guide is specific to implementing the SDK itself. There are a number of breaking changes in v0.19, mainly to the way the SDK is structured. To upgrade you should follow three steps, which are outlined in the breaking changes section below. Uninstall sdk-react (if used) and [install the latest sdk-react-core](/react-sdk/upgrade#sdk-react-sdk-react-core). [Install the WalletConnectors you need](/react-sdk/upgrade#walletconnectors) alongside the SDK and [use them in the DynamicContextProvider](/react-sdk/upgrade#using-walletconnectors). If you're happy for Viem to be the default instead of Ethers, do nothing. Otherwise, [use the Ethers extension](/react-sdk/upgrade#ethers-viem). ### Breaking Changes #### sdk-react -> sdk-react-core