> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating a Dynamic Client

> The first step in using the JavaScript SDK is to create a Dynamic Client

<strong>Important:</strong> All other methods in the JavaScript SDK require a Dynamic client to be created first.

## Installation

```bash theme={"system"}
npm install @dynamic-labs-sdk/client
```

## Usage

Create the client in a module that loads once (for example `dynamicClient.ts` in a React app) and share that instance across your app. The API is the same in React and plain JavaScript.

<Tabs>
  <Tab title="Web">
    ```javascript theme={"system"}
    import { createDynamicClient } from '@dynamic-labs-sdk/client';

    const dynamicClient = createDynamicClient({
      environmentId: 'YOUR_ENVIRONMENT_ID',
      metadata: {
        name: 'YOUR_APP_NAME',
        universalLink: 'https://yourapp.com',
        iconUrl: 'YOUR_APP_ICON_URL',
      },
    });
    ```
  </Tab>

  <Tab title="React Native">
    On React Native, set both `nativeLink` and `universalLink`. `universalLink` is required for passkeys and matches the `window.location` polyfill; `nativeLink` must match the deep link scheme you register in your native projects. Set up polyfills and native configuration first — see [React Native Setup](/docs/javascript/react-native/setup).

    ```typescript theme={"system"}
    import { createDynamicClient } from '@dynamic-labs-sdk/client';

    const dynamicClient = createDynamicClient({
      environmentId: 'YOUR_ENVIRONMENT_ID',
      metadata: {
        name: 'YOUR_APP_NAME',
        nativeLink: 'myapp://', // Must match the scheme registered in Info.plist / AndroidManifest.xml
        universalLink: 'https://yourapp.com', // Required for passkeys; same value as the window.location polyfill
        iconUrl: 'YOUR_APP_ICON_URL',
      },
    });
    ```
  </Tab>
</Tabs>

You can get your environment ID from the [Dynamic dashboard](https://app.dynamic.xyz/dashboard/developer/api).

## Configuration Options

### Basic Options

* `environmentId` (required): Your Dynamic environment ID
* `autoInitialize` (optional): Whether to automatically initialize the client (default: `true`)
* `metadata` (optional): Your app's metadata
  * `name`: The name of your app
  * `universalLink`: The official domain/URL of your app (e.g., `https://yourapp.com`). Used for deep link redirects and as the domain in sign-in message signatures.
  * `iconUrl`: The URL of the icon of your app
  * `nativeLink`: Native deep link for your app (e.g., `myapp://`). Used for app-to-app communication on mobile devices.
* `logLevel` (optional): Logging level for the SDK

### Advanced Options

#### Transformers

Customize SDK data before it's used throughout your application:

```javascript theme={"system"}
const dynamicClient = createDynamicClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  transformers: {
    networksData: (networksData) =>
      networksData.map((network) => {
        // Override RPC URLs
        if (network.networkId === '1') {
          return {
            ...network,
            rpcUrls: {
              http: ['https://eth-mainnet.g.alchemy.com/v2/YOUR-KEY'],
            },
          };
        }
        return network;
      }),
  },
});
```

See [Network Transformers](/docs/javascript/reference/networks/network-transformers) for more details.

#### WaaS Options

The `waas` object tunes the embedded wallet (MPC / Wallet-as-a-Service) behavior. Every option is optional.

```javascript theme={"system"}
const dynamicClient = createDynamicClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  waas: {
    loadTimeoutMs: 5000,
    maxLoadRetries: 0,
  },
});
```

* `loadTimeoutMs` (optional, default `20000`): Per-attempt timeout, in milliseconds, for loading the embedded wallet's secure container. Must be a number between `1000` and `60000`; values outside that range are rejected with an `InvalidParamError` at client creation.
* `maxLoadRetries` (optional, default `1`): Extra load attempts (after the first) before the wallet gives up and embedded wallet operations reject with `WaasLoadFailedError`. Must be an integer between `0` and `10`; values outside that range are rejected with an `InvalidParamError` at client creation.
* `additionalTrustedOrigins` (optional): Extra origins allowed when the WaaS iframe validates `postMessage` sources — for example, when your app is embedded in another trusted origin.

Lower `loadTimeoutMs` and `maxLoadRetries` together to fail fast and drive your own retry cadence on a caught `WaasLoadFailedError`. The worst-case time until that error is `(maxLoadRetries + 1) * loadTimeoutMs + maxLoadRetries * 1000` for the first load cycle.

<Warning>
  This tuning applies process-wide. All chains — and all Dynamic clients on the same page — share one embedded wallet container, and the values are written to shared state whenever a client with an explicit override is constructed. A later client without an override inherits the last explicitly-set values, not the defaults. After an exhausted load cycle, the effective timeout doubles for subsequent cycles (capped at `60000` ms) and never resets for the page's lifetime.
</Warning>
