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

# Migrating from Para v1.x to v2.0

> Guide for migrating from Para version 1.x to Para's version 2.0 release

Use this guide for assistance migrating from Para version 1.x to Para's version 2.0 release.

## React SDK

### Summary of breaking changes

1. The `setup-para` CLI tool needs to run before running your app to ensure all `@getpara` libraries are properly polyfilled. It is recommended to do this in your `postinstall` step of your `package.json`, something like:
   ```bash theme={null}
   "postinstall": "yarn setup-para"
   ```

2. The `ParaProvider` is now required to be used when using the `@getpara/react-sdk`

3. A `queryClient` from `@tanstack/react-query` must be provided.
   <Info>
     See the `@tanstack/react-query` [docs](https://tanstack.com/query/latest/docs/framework/react/quick-start) for more information on setting up a `QueryClient`
   </Info>

4. The `appName` prop has moved from a modal prop to a **required** config prop on the `ParaProvider`. This name will be used throughout the modal and in any external wallet providers that may be used.

5. The `ParaModal` no longer needs to be provided separately, it is automatically included with the `ParaProvider` and all modal props can be passed to the `ParaProvider`.
   <Warning>
     Do not keep a separate `<ParaModal />` next to the embedded modal that `ParaProvider` renders by default. Remove the separate modal and pass modal options through `paraModalConfig`, or set `disableEmbeddedModal: true` in the `ParaProvider` config if you intentionally render your own modal.
   </Warning>

6. The `ParaModal` props, `isOpen` and `onClose`, are no longer required (though they can be provided if desired). These values are now handled by the `ParaProvider` and developers can use the `useModal` hook to control the modal state.

7. When using external wallets the Para connector libraries no longer need to be provided, just installed. All config values for these connectors can be passed to the `ParaProvider`.

### Migration

Migration to V2 can be done one of two ways:

1. (**PREFERRED**) Remove the `ParaModal` component you are providing and use the modal that the updated `ParaProvider` provides. This option offers the most code reduction and overall simpler developer experience.
2. Continue to use the `ParaModal` component you are providing in your app. This option is a bit quicker than the first but will lead to a poorer developer experience.

<Tabs>
  <Tab title="Option 1 (PREFERRED)">
    Remove your `<ParaModal>` and use the one built into `<ParaProvider>`.
    **Starting Code:**

    <CodeGroup>
      ```tsx Starting Code (Existing Provider) theme={null}
      <QueryClientProvider client={YOUR_QUERY_CLIENT}>
        <ParaProvider
          paraClientConfig={{
            apiKey: "YOUR_API_KEY",
          }}
        >
          {...REST_OF_YOUR_APP}
          <ParaModal
            {...YOUR_MODAL_PROPS}
          />
        </ParaProvider>
      </QueryClientProvider>
      ```

      ```tsx Starting Code (Without Existing Provider) theme={null}
      const Para = new Para("YOUR_API_KEY")
      <>
        {...REST_OF_YOUR_APP}
        <ParaModal
          para={Para}
          {...YOUR_MODAL_PROPS}
        />
      </>
      ```
    </CodeGroup>

    **After Migration:**

    ```tsx After Migration {7-11} theme={null}
    <QueryClientProvider client={YOUR_QUERY_CLIENT}>
      <ParaProvider
        paraClientConfig={{
          apiKey: "YOUR_API_KEY",
        }}
        config={{
          appName: 'Your App Name',
        }}
        paraModalConfig={YOUR_MODAL_PROPS_WITHOUT_APP_NAME}
        externalWalletConfig={{ wallets: [] }}
      >
        {...REST_OF_YOUR_APP}
        {/* Note: <ParaModal /> is removed from here */}
      </ParaProvider>
    </QueryClientProvider>
    ```
  </Tab>

  <Tab title="Option 2">
    <p>Continue using your own `<ParaModal>` by disabling the built-in one.</p>
    **Starting Code:**

    <CodeGroup>
      ```tsx Starting Code (Existing Provider) theme={null}
      <QueryClientProvider client={YOUR_QUERY_CLIENT}>
        <ParaProvider
          paraClientConfig={{
            apiKey: "YOUR_API_KEY",
          }}
        >
          {...REST_OF_YOUR_APP}
          <ParaModal
            {...YOUR_MODAL_PROPS}
          />
        </ParaProvider>
      </QueryClientProvider>
      ```

      ```tsx Starting Code (Without Existing Provider) theme={null}
      const Para = new Para("YOUR_API_KEY")
      <>
        {...REST_OF_YOUR_APP}
        <ParaModal
          para={Para}
          {...YOUR_MODAL_PROPS}
        />
      </>
      ```
    </CodeGroup>

    **After Migration:**

    ```tsx After Migration {8-10, 16} theme={null}
    <QueryClientProvider client={YOUR_QUERY_CLIENT}>
      <ParaProvider
        paraClientConfig={{
          apiKey: "YOUR_API_KEY",
        }}
        config={{
          appName: 'Your App Name',
          // This is the key to providing a `ParaModal` elsewhere in your app
          disableEmbeddedModal: true,
        }}
        externalWalletConfig={{ wallets: [] }}
      >
        {...REST_OF_YOUR_APP}
        <ParaModal
          {...YOUR_MODAL_PROPS_WITHOUT_APP_NAME}
        />
      </ParaProvider>
    </QueryClientProvider>
    ```
  </Tab>
</Tabs>

### Adding External Wallets

If you're using external wallets with Para currently, those configs can now be passed to the `ParaProvider` and the connectors will be instantiated for you. Assuming you already followed the migration steps above, a successful migration would look like:

<CodeGroup>
  ```tsx Starting Code [expandable] theme={null}
  <ParaCosmosProvider
    selectedChainId={SELECTED_CHAIN_STATE}
    chains={YOUR_COSMOS_CHAINS}
    wallets={[keplrWallet]}
    onSwitchChain={chainId => {
      SELECTED_CHAIN_STATE_UPDATER_FN();
    }}
    multiChain
    walletConnect={{ options: { projectId: 'YOUR_WALLETCONNECT_PROJECT_ID' } }}
  >
    <ParaEvmProvider
      config={{
        projectId: 'YOUR_WALLETCONNECT_PROJECT_ID',
        appName: 'Your App Name',
        chains: YOUR_WAGMI_CHAINS,
        wallets: [metaMaskWallet],
      }}
    >
      <ParaSolanaProvider
        endpoint={YOUR_SOLANA_ENDPOINT}
        wallets={[backpackWallet]}
        chain={YOUR_SOLANA_NETWORK}
        // Refer to [https://docs.solanamobile.com/reference/typescript/mobile-wallet-adapter#web3mobilewalletauthorize](https://docs.solanamobile.com/reference/typescript/mobile-wallet-adapter#web3mobilewalletauthorize) for how appIdentity fields work
        appIdentity={{ name: 'Your App Name', uri: 'YOUR_APP_URL' }}
      >
        {...REST_OF_YOUR_APP}
      </ParaSolanaProvider>
    </ParaEvmProvider>
  </ParaCosmosProvider>
  ```

  ```tsx After Migration {11-41} [expandable] theme={null}
  <QueryClientProvider client={YOUR_QUERY_CLIENT}>
    <ParaProvider
      paraClientConfig={{
        apiKey: "YOUR_API_KEY",
      }}
      config={{
        appName: 'Your App Name',
      }}
      paraModalConfig={YOUR_MODAL_PROPS_WITHOUT_APP_NAME}
      externalWalletConfig={{
        wallets: [ExternalWallet.METAMASK, ExternalWallet.KEPLR, ExternalWallet.BACKPACK],
        appUrl: 'YOUR_APP_URL',
        evmConnector: {
          config: {
            chains: YOUR_WAGMI_CHAINS,
          },
          // wagmiProviderProps={}
        },
        cosmosConnector: {
          config: {
            selectedChainId: SELECTED_CHAIN_STATE,
            multiChain: true,
            onSwitchChain: chainId => {
              SELECTED_CHAIN_STATE_UPDATER_FN();
            },
            chains: YOUR_COSMOS_CHAINS,
          },
          // grazProviderProps={}
        },
        solanaConnector: {
          config: {
            endpoint: YOUR_SOLANA_ENDPOINT,
            chain: YOUR_SOLANA_NETWORK,
          },
        },
        walletConnect: {
          projectId: 'YOUR_WALLETCONNECT_PROJECT_ID',
        },
      }}
    >
      {...REST_OF_YOUR_APP}
    </ParaProvider>
  </QueryClientProvider>
  ```
</CodeGroup>

<Note>
  Notes on the external wallet migration:

  1. All wallets are provided by default, if you wish for them all to be provided you can remove the `wallets` value in the `externalWalletConfig`
  2. If you only wish to use EVM wallets only the `evmConnector` config needs to be passed, the other connectors will be skipped in that case.
</Note>

## Pregen Wallet Methods

Methods dealing with pregen wallets now use a simpler object-based notation to specify the type and identifier the wallet belongs to.

<CodeGroup>
  ```tsx Email theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: 'email@email.com',
    pregenIdentifierType: 'EMAIL'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { email: 'email@email.com' } });
  ```

  ```tsx Phone theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: '+13105551234',
    pregenIdentifierType: 'PHONE'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { phone: '+13105551234' } });
  ```

  ```tsx Farcaster theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: 'FarcasterUsername',
    pregenIdentifierType: 'FARCASTER'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { farcasterUsername: 'FarcasterUsername' } });
  ```

  ```tsx Telegram theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: '1234567890',
    pregenIdentifierType: 'TELEGRAM'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { telegramUserId: '1234567890' } });
  ```

  ```tsx Discord theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: 'DiscordUsername',
    pregenIdentifierType: 'DISCORD'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { discordUsername: 'DiscordUsername' } });
  ```

  ```tsx X (Twitter) theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: 'XUsername',
    pregenIdentifierType: 'TWITTER'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { xUsername: 'XUsername' } });
  ```

  ```tsx Custom ID theme={null}
  // 1.x
  await para.createPregenWallet({
    pregenIdentifier: 'my-custom-id',
    pregenIdentifierType: 'CUSTOM_ID'
  });

  // 2.x
  await para.createPregenWallet({ pregenId: { customId: 'my-custom-id' } });
  ```
</CodeGroup>

## Common Enums (optional)

Enum types used in certain methods, while still available, are now replaced with string union types. You will not be required to import these enums for methods that accept them.

```tsx {4} theme={null}
import { WalletType } from '@getpara/web-sdk';

// Either is allowed
para.createWallet({ type: WalletType.EVM });

para.createWallet({ type: 'EVM' });
```

### Type Definitions

<ResponseField name="WalletType" type="string">
  <Expandable title="values">
    <ResponseField name="'EVM'" type="string">
      Ethereum Virtual Machine compatible wallet
    </ResponseField>

    <ResponseField name="'SOLANA'" type="string">
      Solana wallet
    </ResponseField>

    <ResponseField name="'COSMOS'" type="string">
      Cosmos wallet
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="WalletScheme" type="string">
  <Expandable title="values">
    <ResponseField name="'DKLS'" type="string">
      DKLS wallet scheme
    </ResponseField>

    <ResponseField name="'ED25519'" type="string">
      ED25519 wallet scheme
    </ResponseField>

    <ResponseField name="'CGGMP'" type="string">
      CGGMP wallet scheme
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="OAuthMethod" type="string">
  <Expandable title="values">
    <ResponseField name="'GOOGLE'" type="string">
      Google OAuth
    </ResponseField>

    <ResponseField name="'APPLE'" type="string">
      Apple OAuth
    </ResponseField>

    <ResponseField name="'TWITTER'" type="string">
      Twitter/X OAuth
    </ResponseField>

    <ResponseField name="'DISCORD'" type="string">
      Discord OAuth
    </ResponseField>

    <ResponseField name="'FACEBOOK'" type="string">
      Facebook OAuth
    </ResponseField>

    <ResponseField name="'TELEGRAM'" type="string">
      Telegram OAuth
    </ResponseField>

    <ResponseField name="'FARCASTER'" type="string">
      Farcaster OAuth
    </ResponseField>
  </Expandable>
</ResponseField>

## Auth Objects

User identity attestations are now represented as auth objects with a single key and value, representing both the type of attestation and the relevant identifier. These objects are used for methods that require an attestation of this type, primarily those for authentication and pregenerated wallet management.

### Auth Object Examples

<CodeGroup>
  ```tsx Email theme={null}
  const auth = { email: 'email@test.com' };

  await para.signUpOrLogIn({ auth });
  ```

  ```tsx Phone theme={null}
  const auth = { phone: '+13105551234' };

  await para.signUpOrLogIn({ auth });
  ```

  ```tsx Farcaster theme={null}
  const pregenId = { farcasterUsername: 'MyUsername' };

  await para.createPregenWallet({ pregenId, type: 'EVM' });
  ```

  ```tsx Telegram theme={null}
  const pregenId = { telegramUserId: '1234567890' };

  await para.createPregenWallet({ pregenId, type: 'EVM' });
  ```

  ```tsx Discord theme={null}
  const pregenId = { discordUsername: 'MyUsername' };

  await para.createPregenWallet({ pregenId, type: 'EVM' });
  ```

  ```tsx X/Twitter theme={null}
  const pregenId = { xUsername: 'MyUsername' };

  await para.createPregenWallet({ pregenId, type: 'EVM' });
  ```

  ```tsx Custom Pregen ID theme={null}
  const pregenId = { customId: 'my-custom-id' };

  await para.createPregenWallet({ pregenId, type: 'EVM' });
  ```
</CodeGroup>

<Note>
  Phone number auth objects expect a string in international format, beginning with a `+` and containing only numbers without spaces or extra characters, i.e.: `+${number}`. If your UI deals in separated country codes and national phone numbers, you may use the exported `formatPhoneNumber` function to combine them into a correctly formatted string.
</Note>

```tsx theme={null}
import { formatPhoneNumber } from '@getpara/web-sdk';

await para.signUpOrLogIn({ auth: { phone: '+13105551234' } });

// or, if your country code and national number are distinct:
await para.signUpOrLogIn({ auth: { phone: formatPhoneNumber('3105551234', '1') } });
```

## Cancelable Methods (optional)

<Info>
  This feature is available in the following SDKs:

  * `@getpara/web-sdk`
  * `@getpara/react-sdk`
  * `@getpara/react-native-sdk`
</Info>

For methods that wait for user action, such as `waitForLogin`, you may now pass a callback that is invoked on each polling interval, as well as a callback to indicate whether the method should be canceled and another invoked upon cancelation.

```tsx theme={null}
let i = 0, popupWindow: Window;

await para.waitForLogin({
  isCanceled: () => popupWindow?.closed,
  onPoll: () => {
    console.log(`Waiting for login, polled ${++i} times...`)
  },
  onCancel: () => {
    console.log('Login canceled after popup window closed!');
  }
});
```

## New Authentication Flow

The primary methods for authenticating via phone, email address, or third-party services have been overhauled and greatly simplified. If you are using a custom authentication UI, refer to the [Custom Authentication UI](/v3/react/guides/custom-ui-simplified) page for detailed instructions and code samples. For new developers, the [Para Modal](/v3/react/overview) is the preferred option to handle user authentication in your app.

## Modified Core Methods

We've streamlined and improved several core methods in version 2.0.0. The following sections outline what's changed and what actions you need to take.

<Warning>
  These changes are required when upgrading to version 2.0.0. Make sure to update your code accordingly to avoid breaking your application.
</Warning>

<AccordionGroup>
  <Accordion title="Authentication Methods">
    <ResponseField name="Previous Methods">
      * `checkIfUserExists`
      * `initiateUserLogin`
      * `createUser`
      * `checkIfUserExistsByPhone`
      * `initiateUserLoginForPhone`
      * `createUserByPhone`
    </ResponseField>

    <ResponseField name="New Method">
      `signUpOrLogIn`
    </ResponseField>

    <ResponseField name="Action Required">
      Modify your current authentication flow to use the new simplified `signUpOrLogIn` method as detailed on our <a href="/v3/react/guides/custom-ui-simplified">Custom Authentication UI</a> page.
    </ResponseField>

    <Info>
      This change simplifies the authentication process by consolidating multiple methods into a single, more intuitive function.
    </Info>
  </Accordion>

  <Accordion title="Authentication Polling">
    <ResponseField name="Previous Methods">
      * `waitForLoginAndSetup`
      * `waitForAccountCreation`
      * `waitForPasskeyAndCreateWallet`
    </ResponseField>

    <ResponseField name="New Methods">
      * `waitForLogin`
      * `waitForSignup`
      * `waitForWalletCreation`
    </ResponseField>

    <ResponseField name="Action Required">
      Modify your current authentication flow to use the new simplified methods as detailed on our <a href="/v3/react/guides/custom-ui-simplified">Custom Authentication UI</a> page.
    </ResponseField>
  </Accordion>

  <Accordion title="Pregen Wallet Methods">
    <ResponseField name="Previous Methods">
      * `createPregenWallet`
      * `createPregenWalletPerType`
      * `updatePregenWalletIdentifier`
      * `hasPregenWallet`
      * `claimPregenWallets`
    </ResponseField>

    <ResponseField name="Changes">
      Modified to accept a single `pregenId` argument
    </ResponseField>

    <ResponseField name="Action Required">
      Update your functions to use the new notation.
    </ResponseField>

    <CodeGroup>
      ```javascript Before theme={null}
      para.createPregenWallet({
        pregenIdentifier: 'email@email.com',
        pregenIdentifierType: 'EMAIL'
      })
      ```

      ```javascript After theme={null}
      para.createPregenWallet({
        pregenId: {
          email: 'email@email.com'
        }
      })
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Farcaster Methods">
    <ResponseField name="Previous Methods">
      * `initiateFarcasterLogin`
      * `waitForFarcasterStatus`
    </ResponseField>

    <ResponseField name="New Method">
      `verifyFarcaster`
    </ResponseField>

    <ResponseField name="Action Required">
      Use the simplified `verifyFarcaster` method as detailed on our <a href="/v3/react/guides/custom-ui-simplified">Custom Authentication UI</a> page.
    </ResponseField>
  </Accordion>

  <Accordion title="OAuth Methods">
    <ResponseField name="Previous Methods">
      * `getOAuthUrl`
      * `waitForOAuth`
    </ResponseField>

    <ResponseField name="New Method">
      `verifyOAuth`
    </ResponseField>

    <ResponseField name="Action Required">
      Use the simplified `verifyOAuth` method as detailed on our <a href="/v3/react/guides/custom-ui-simplified">Custom Authentication UI</a> page.
    </ResponseField>
  </Accordion>

  <Accordion title="Session Methods">
    <ResponseField name="Method">
      `touchSession`
    </ResponseField>

    <ResponseField name="Changes">
      Destructuring is simpler, returning an object of type `SessionInfo` rather than `{ data: SessionInfo }`
    </ResponseField>

    <ResponseField name="Action Required">
      Update existing usages to destructure the return value correctly.
    </ResponseField>
  </Accordion>

  <Accordion title="2FA Methods">
    <ResponseField name="Previous Methods">
      * `check2FAStatus` (Deprecated)
      * `enable2FA`
      * `verify2FA`
      * `setup2FA`
    </ResponseField>

    <ResponseField name="New Methods">
      * `setup2fa` (Replaces `check2FAStatus`)
      * `enable2fa`
      * `verify2fa`
    </ResponseField>

    <ResponseField name="Action Required">
      * Replace calls to `check2FAStatus` with `setup2fa`, which will now either return `{ isSetup: true }` or `{ isSetup: false, uri: string }` depending on the current user's settings
      * Update function instances to use the new spelling with lowercase "fa"
    </ResponseField>
  </Accordion>

  <Accordion title="Platform-Specific Methods">
    <ResponseField name="Platform">
      React Native, Flutter, Swift
    </ResponseField>

    <ResponseField name="Previous Method">
      `login`
    </ResponseField>

    <ResponseField name="New Method">
      `loginWithPasskey`
    </ResponseField>

    <ResponseField name="Action Required">
      Update function instances to use the new name.
    </ResponseField>
  </Accordion>
</AccordionGroup>
