npm package: @notifi-network/notifi-react
Description: React components to access Notifi core services
Author: eric-notifi
Latest version: 8.0.0

# Notifi React SDK

`@notifi-network/notifi-react` accelerates the development of Notifi integrated dapps.

- [Out of The Box Implementation](#out-of-the-box-implementation)
- [Customized Implementation](#advanced-customized-implementation)
- [Custom Integration](#custom-integration)
- [Migrating from an older version of the SDK ](#migrate-your-card)

> Play around with a Card [Example](notifi-sdk-ts-notifi-dapp-example.vercel.app)

<br/><br/>

# Out of The Box Implementation

Dapp developers can easily mount the `NotifiCardModal` component to their dapp to enable the Notifi notification service. The `NotifiCardModal` component provides the following features to the user:

- Login to Notifi Services

- Manage Subscriptions to Notifications

- Manage Targets/Channels for Notifications

- Preview Notification Details

<br/><br/>

## Getting Started

_Environment_

- Node version >= 18 (with corresponding npm version)
- React version >= 17

> If you haven't created a Notifi tenant account yet [set up an account](https://admin.notifi.network/signup?environment=prd)

<br/><br/>

### Mount the `NotifiCardModal` to your dApp

#### Prerequisites (**IMPORTANT**)

- To use `NotifiCardModal`, you need to wrap your component with `NotifiContextProvider` first.
- Notifi supports both `on-chain` and `off-chain` authentication. The authentication method differs based on the `LoginParamsWithUserParams` [type](https://github.com/notifi-network/notifi-sdk-ts/blob/55b6d24c90d962e5ae4e20508015904754edbf0f/packages/notifi-react/lib/context/NotifiFrontendClientContext.tsx#L56) passed to the `NotifiContextProvider`.
  - For `on-chain` authentication, `walletBlockchain='<blockchain>'`, `signMessage` callback function, and the respective `wallet keys or addresses` for the `blockchain` are required. The common EVM blockchain example is shown above.
  - For `off-chain` authentication, `walletBlockchain='OFF_CHAIN'`, `signIn` callback function, and `userAccount` are required. `userAccount` can be any user-related unique identifier derived from a JWT token. The Google off-chain OIDC authentication example is shown below.

#### **Example Quick Start for Ethereum (On chain)**

```tsx
import {
  NotifiCardModal,
  NotifiContextProvider,
} from '@notifi-network/notifi-react';
import { useEthers } from '@usedapp/core';
import { providers } from 'ethers';

const NotifiCard = () => {
  const { account, library } = useEthers();
  const signer = useMemo(() => {
    if (library instanceof providers.JsonRpcProvider) {
      return library.getSigner();
    }
    return undefined;
  }, [library]);

  if (account === undefined || signer === undefined) {
    // account is required
    return null;
  }

  return (
    //tenantId/dAppId and cardId are found on the Notifi Tenant Portal. Please see Docs below.
    <NotifiContextProvider
      tenantId="YOUR_TENANT_ID"
      env="Production"
      cardId="YOUR_CARD_ID"
      signMessage={signMessage}
      walletBlockchain="ETHEREUM"
      walletPublicKey={account}
      {/* ... other optional props */}
    >
      <NotifiCardModal {/* ... other optional props ex. darkMode */} />
    </NotifiContextProvider>
  );
};
```

#### **Example Quick Start for google OIDC (Off chain)**

```tsx
const NotifiCard = () => {
  // ... other codes
  const jwt = '<the-oidc-id-token-here>';
  const userAccount = jwtDecode(jwt).email; // or any unique identifier
  const signIn: OidcSignInFunction = async () => {
    return {
      oidcProvider: 'GOOGLE',
      jwt,
    };
  };

  return (
    <NotifiContextProvider
      tenantId="YOUR_TENANT_ID"
      env="Production"
      cardId="YOUR_CARD_ID"
      walletBlockchain={'OFF_CHAIN'}
      userAccount={userAccount}
      signIn={signIn}
      {/* ... other optional props */}
    >
      <NotifiCardModal {/* ... other optional props ex. darkMode */} />
    </NotifiContextProvider>
  );
};
```

**Reference**

> - [Getting start Docs](https://docs.notifi.network/docs/getting-started)
> - Notifi supported blockchains: [WalletBlockchain Enum document](https://graphdoc.io/preview/enum/WalletBlockchain?endpoint=https://api.dev.notifi.network/gql/)
> - Notifi supported OIDC providers: [OidcProvider Enum document](https://graphdoc.io/preview/enum/OidcProvider?endpoint=https://api.dev.notifi.network/gql/)
> - To enable OIDC login, it requires additional setup to integrate your OIDC provider with Notifi tenant using [Notifi Admin Portal](https://admin.notifi.network/) check on the Notifi Documentation **(WIP: coming soon)**

<br/><br/>

# Customize NotifiCardModal component

`NotifiCardModal` is fully customizable using **global CSS overrides** and **optional properties**.

<br/>

## Global CSS overrides

By overriding the default CSS classes, we can style the elements in the card.
[Default CSS Classes are found here.](https://github.com/notifi-network/notifi-sdk-ts/tree/main/packages/notifi-react/lib/style)

Before overriding the CSS classes, we need to adopt the default style of the `NotifiCardModal` component. To do this, we need to import the default CSS file from the `@notifi-network/notifi-react` package like below.

_Example_

```tsx
import '@notifi-network/notifi-react/dist/index.css';
```

> - Make sure this import is placed at the top level of the component file. [complete example](https://github.com/notifi-network/notifi-sdk-ts/blob/97280b625ef133811d176fbb8add73f6b3f7bd44/packages/notifi-react-example-v2/src/components/OidcGoogle.tsx#L9)
>   Find the overrideable CSS classes [here](https://github.com/notifi-network/notifi-sdk-ts/tree/97280b625ef133811d176fbb8add73f6b3f7bd44/packages/notifi-react/lib/style)

<br/><br/>

## Other Optional Properties

`NotifiCardModal` component provides the following additional optional properties to customize the card even further:

- [darkMode](#adjusting-card-color-scheme---darkmode)
- [globalCtas](#additional-optional-cta-call-to-action---globalctas)
- [copy](#customizing-the-card-copy---copy)
- [classNames](#embedding-custom-css-classes-in-components---classnames)

> Check out the [NotifiCardModalProps type documentation ](https://docs.notifi.network/notifi-sdk-ts/notifi-react/types/NotifiCardModalProps.html) to know more details

<br/>

#### Adjusting card color scheme - `darkMode`

The `darkMode` property allows you to switch the card color scheme between light and dark mode.

> Default scheme: `light` (light mode)

**Example**

```tsx
<NotifiCardModal darkMode />
```

<br/>

#### Additional optional CTA (Call to Action) - `globalCtas`

The `globalCtas` property allows to add certain supported CTAs to the card. Now it supports `onClose` CTA.

**Example**

```tsx
// ...
const [isCardModalOpen, setIsCardModalOpen] = useState(false);

// ...

{
  isCardModalOpen ? (
    <NotifiCardModal
      globalCtas={{ onClose: () => setIsCardModalOpen(false) }}
    />
  ) : null;
}
```

**NOTE**

The `onClose` function enables the close-icon on the card. We are passing a callback function here to update the local state and close the modal.

![close-icon-preview](https://github.com/user-attachments/assets/79de998f-9807-45cc-a4d7-583e6298d2e7)

<br/>

#### Customizing the card copy - `copy`

The `copy` property allows you to customize the card's default copy.

There are many customizable copy sections in the NotifiCardModal component. Check out the [NotifiCardModalProps type documentation ](https://docs.notifi.network/notifi-sdk-ts/notifi-react/types/NotifiCardModalProps.html) to know more details

**Common Example: Customizing the Connect view footer**

Connect view footer preview as seen below:

![custom-footer-content](https://github.com/user-attachments/assets/8156b76b-2f8b-47a2-9a3e-d640fc8a4ae1)

_Example code_

```tsx
const YourComponent = () => {
  // ...
  const { frontendClientStatus } = useNotifiFrontendClientContext();
  const customCopy: NotifiCardModalProps['copy'] = {
    Connect: {
      footerContent: [
        {
          type: 'plain-text',
          text: 'This is an example of some footer content that may link to a ',
        },
        {
          type: 'hyperlink',
          text: 'privacy policy',
          url: 'https://notifi.network',
        },
        { type: 'plain-text', text: ' and ' },
        {
          type: 'hyperlink',
          text: 'terms of service',
          url: 'https://notifi.network',
        },
      ],
    },
    // ... other copy customization
  };

  return (
    <>
      {/*  ... */}
      <NotifiCardModal copy={customCopy} />
      {/*  ... */}
    </>
  );
};
```

> - Checkout the example project [codebase](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-react-example-v2/src/app/notifi/components-example/page.tsx)

<br/>

#### Embedding custom CSS classes in components - `classNames`

You can pass in custom CSS classes to the `NotifiCardModal` component.
Check out the `classNames` property in [NotifiCardModalProps type documentation ](https://docs.notifi.network/notifi-sdk-ts/notifi-react/types/NotifiCardModalProps.html) to know the className customizable components.

_Example_

```tsx
const YourComponent = () => {
  // ...
  const customClassName: NotifiCardModalProps['classNames'] = {
    container: 'custom-card-modal-container', // This will add 'custom-card-modal-container' class to the card modal container
  };

  return (
    <>
      {/*  ... */}
      <NotifiCardModal classNames={customClassName} />
      {/*  ... */}
    </>
  );
};
```

<br/><br/>

# Custom Integration

If you want to build your own UI components instead of using the `NotifiCardModal`, you can use the Notifi React Context to access the Notifi core services.

<br/><br/>

### Important Notifi React Contexts:

- **NotifiContextProvider**: A provider to wrap your dapp with all Notifi contexts.
- **Specific Context Providers**:
  - **NotifiFrontendClientContext**: Provides the Notifi Frontend Client instance and user authentication status (Authenticated, Initiated, or Expired)
  - **NotifiTenantConfigContext**: Provides the tenant configuration.
  - **NotifiUserSettingContext**: Provides available user methods and states
  - **NotifiTargetContext**: Provides Notifi Target related methods and state.
  - **NotifiTopicContext**: Provides Topic related methods and state.

> By wrapping your app with `NotifiContextProvider`, you can access the Notifi services in your dapp.

_Example_

```tsx
import { NotifiContextProvider } from '@notifi-network/notifi-react';

const App = () => {
  const params = {
    // params for contexts
  };
  return (
    <NotifiContextProvider {...params}>
      <MyComponent />
    </NotifiContextProvider>
  );
};
```

Or use particular contexts to access specific Notifi services.

```tsx
import {
  NotifiFrontendClientProvider,
  NotifiTenantConfigProvider,
} from '@notifi-network/notifi-react';

const App = () => {
  const params = {
    // params for contexts
  };
  return (
    <NotifiFrontendClientProvider {...params}>
      <NotifiTenantConfigProvider {...params}>
        <MyComponent />
      </NotifiTenantConfigProvider>
    </NotifiFrontendClientProvider>
  );
};
```

<br></br>

## **NotifiFrontendClientContext**

Provides the Notifi Frontend Client and the user authentication status.

_Example_

```tsx
import { useNotifiFrontendClientContext } from '@/context/NotifiFrontendClientContext';

export const MyComponent = () => {
  const { login, frontendClientStatus, frontendClient } =
    useNotifiFrontendClientContext();

  // Other code ...
};
```

**Methods**

- **login**: A function to trigger the login process.

- **frontendClientStatus**: The status of the frontend client, it can be one of the following:
  - **initiated**: The frontend client/user has been initiated but not authenticated.
  - **authenticated**: The frontend client/user is authenticated.
  - **expired**: The frontend client/user is authentication/authorization expired.
- **frontendClient**: The frontend client instance, used to interact with the Notifi backend services.
- **loginViaTransaction**: SDK allows Dapp to auto login the user by utilizing this property. See the following detailed information.

  We can improve the user experience by auto-login the users as soon as they sign a transaction. This way, users no longer need to manually sign a message to login to Notifi. The `loginViaTransaction` property is used to achieve this feature.

  **Step1**: Wrap higher (top) level of dapp components with `<NotifiContextProvider>` (or `<NotifiFrontendClientProvider> `).
  **Step2**: put the `loginViaTransaction.nonce` as memo when user signs a transaction.
  **Step3**: Pass in the signature from `Step#2` to the `loginViaTransaction.login` method.

  <details>
  <summary>Example for EVM dapp</summary>

  **Case 1**: Plain transaction

  ```ts
  // Any component in the dapp which has access to the NotifiFrontendClientContext
  const {
    walletWithSignParams,
    loginViaTransaction: {
      nonce: nonceForTransactionLogin,
      login: loginViaTransaction,
    },
  } = useNotifiFrontendClientContext();
  // EVM transaction (Other supported chains also work in similar manner)
  const memo = nonceForTransactionLogin;
  const signature = await transactionSigner.request({
    method: 'eth_sendTransaction',
    params: [
      {
        from: walletWithSignParams.walletPublicKey,
        // ...
        data: memo,
      },
    ],
  });
  loginViaTransaction(signature);
  ```

  **Case 2**: smart contract transaction

  ```ts
  const {
    walletWithSignParams,
    loginViaTransaction: {
      nonce: nonceForTransactionLogin,
      login: loginViaTransaction,
    },
  } = useNotifiFrontendClientContext();

  const smartContract = new ethers.Contract(
    `<contract-address>`,
    `<contract-abi>`,
    provider.getSigner(),
  );

  // Assume the smart contract has an "example" method with one argument uint amount
  const amount = ethers.utils.parseUnits('0.1', 'ether');

  // Step 1: Get the calldata for the smart contract method call
  const calldata = smartContract.interface.encodeFunctionData('example', [
    amount,
  ]);

  // Step 2: Append notifi nonce to the calldata
  const txParams = {
    to: smartContract.address,
    data: calldata + nonceForTransactionLogin.replace('0x', ''),
  };

  // Step 3: Sign the transaction with new calldata
  const { hash } = await provider.getSigner().sendTransaction(txParams);

  // Step 4: Use the transaction signature to login to notifi
  loginViaTransaction(hash);
  ```

  **IMPORTANT NOTE**:

  - **Browser extension constraints**: Some browser extensions (Metamask ...) do not allow appending additional info to the calldata of particular smart contract method (example: Token contract (ERC20, ERC721 ...etc)). Browser extension (Metamask) will throw `Message: Invalid token value; should be exactly xx hex digits long` error in this case.

  </details>

## **NotifiTenantConfigContext**

Provides the tenant configuration.

```tsx
import { useNotifiTenantConfigContext } from '@/context/NotifiTenantConfigContext';

export const MyComponent = () => {
  const { cardConfig, inputs, isLoading, error, fusionEventTopics } =
    useNotifiTenantConfigContext();

  // Other code ...
};
```

- **cardConfig**: The card UI configuration set in Notifi Admin portal.
- **fusionEventTopics**: The detailed information of the fusion event topics in the specific UI card config. [Interface.](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-react/lib/context/NotifiTenantConfigContext.tsx#L18)
- **inputs**: `input` is a concept which is used when a dynamic topic subscription value needs to be adopted. The `input` is a key-value pair object. The key is the value associated with the `Create a new topic` section in Admin Portal. The value is the dynamic value that needs to be passed into the topic subscription. The value needs to be an array of [InputObject](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-frontend-client/lib/models/FusionEvent.ts#L24) interface.

<br></br>

**Example**:

We want to allow a user to subscribe the topic which relates to his/her specific wallet address' state (eg, a transaction signed by the wallet). In this case, we need to pass the wallet address to the topic subscription. The `input` is where we would store the dynamic value.

<br></br>

![Notifi Admin Portal UX](https://i.imgur.com/eJlqMdZ.png)

**Case 1**: `Wallet Address` is selected, the key is set to `walletAddress`. So the `input` will be

```
 input={ walletAddress: [{label: '', '<USER_WALLET_ADDRESS_GOES_HERE>'}] }
```

**Case 2**: `No input From User` is selected, we do not need to specify the `inputs` object.

**Case 3**: `User Selects From List` is selected with a self-defined value. It means we want to allow users to select preferred targets to subscribe.

- **Example**:  
  We want to allow users to define multiple smart contracts' state change (eg. staked value changed). So we want to provide a list of options for users to select. If we set `farm` in Admin portal UX in `User Selects From List` section. And we want to allow to have `BTC/ETH farm` and `BTC/USDT farm`, we can set the `inputs` object to `{ farm: [{label: 'BTC/ETH farm', value: 'BTC-ETH'}, {label: 'BTC/USDT farm', value: 'BTC-USDT'}] }`. The `value` is the value that will be passed to the topic subscription.

> **NOTE** the `value` in the `InputObject` should associate with the subscription value in the parser. `label` is the display name in the UI.
>
> - [Additional Documentation](https://docs.notifi.network/docs/next/notifi-hosted-development)

<br></br>

## **NotifiUserSettingContext**

Provides user specific methods and state.

```tsx
import { useNotifiUserSettingContext } from '@notifi-network/notifi-react';

export const MyComponent = () => {
  const { ftuStage, updateFtuStage, isLoading, error } =
    useNotifiUserSettingContext();
  // Other code ...
};
```

**Methods**

- **ftuStage**: The current First Time User stage of the user.

- **updateFtuStage**: A function to update the FTU stage of the user.

<br></br>

## **NotifiTargetContext**

Provides the Notifi Target related methods and state.
`Target` is an important concept in Notifi. It is the destination which need to be notified when the specific event is triggered. Notifi currently supports the following targets:

- Email
- Telegram
- SMS
- Discord
- Slack
- Want another destination? [Email Us](sales@notifi.network)

_Example_

```tsx
import { useNotifiTargetContext } from '@notifi-network/notifi-react';

export const MyComponent = () => {
  const {
    error,
    isLoading,
    renewTargetGroup,
    unVerifiedTargets,
    isChangingTargets,
    targetDocument: {
      targetGroupId,
      targetInputs,
      targetData,
      targetInfoPrompts,
    },
    updateTargetInputs,
  } = useNotifiTargetContext();

  // Other code ...
};
```

**Methods**

- **renewTargetGroup**: A function to renew the target group. `targetGroup` is a group of targets which owned by the user.

- **unVerifiedTargets**: The list of targets which are not verified yet.

- **targetInputs**: The targetInputs is the temporary storage which reflects the on-demand target input changes. It is used to store the target input changes before the user confirms the changes.

- **isChangingTargets**: if a target is undergoing a change, it means the users are changing the target inputs and has unsaved changes.

- **targetInfoPrompts**: The targetInfoPrompts is the prompt message which is used to guide the user to input the target destination information.

- **updateTargetInputs**: A function to update the target inputs. It is used to update the target when the user changes/finalizes the target inputs.

- **renewTargetGroup**: A function to update the backend target state according to the targetInputs.

  - **Update single target**: passing `singleTargetRenewArgs` as an argument. **NOTE**: This action does not require updating `targetInputs` manually. `targetInputs` will be updated automatically once `renewTargetGroup` is called successfully.
  - **Update all targets**: all targets will be updated according to the `targetInputs` state w/o passing any argument.

- **TargetGroupId**: The target group id which is the argument to call `renewTargetGroup` function.

- **targetData**: The target data which is the current state of the targets in the backend.

> **!!IMPORTANT NOTE**: targetData.wallet
>
> For version 6.0.0 or above, Please use `NotifiContextProviderWalletTargetPlugin` context in `@notifi-network/notifi-react-wallet-target-plugin` if Target.wallet.isAvailable is set to `true`. For more details, refer to `@notifi-network/notifi-react-wallet-target-plugin` README.

<br></br>

## **NotifiTopicContext**

Provide the topic related methods and state.
`Topic` is an important concept in Notifi. It is the prototype that shapes the event which will be triggered. Users are able to `subscribe` to certain topics in order to receive the notification when the event is triggered.

> **IMPORTANT CONCEPT**
> Once a user subscribes to a topic, Notifi Service creates an `Alert` object associated to the users with the respective topic.
> [Additional Information.](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-react/lib/context/NotifiTopicContext.tsx#L60)

_Example_

```tsx
import { useNotifiTopicContext } from '@notifi-network/notifi-react';

export const MyComponent = () => {
  const {
    isLoading,
    error,
    subscribeAlertsDefault,
    unsubscribeAlerts,
    isAlertSubscribed,
    subscribeAlertsWithFilterOptions,
    getAlertFilterOptions,
    getTopicStackAlerts,
  } = useNotifiTopicContext();

  // Other code ...
};
```

**Methods**

- **subscribeAlertsDefault**: A function to subscribe to the respective topic with the default filterOptions. This will create an alert configuration for the user.

- **unsubscribeAlerts**: A function to unsubscribe to the respective topics. This will remove target alerts from the user's alert list.

- **isAlertSubscribed**: A function to check if the topic is subscribed (This checks whether an alert configuration exists).

- **subscribeAlertsWithFilterOptions**: A function to subscribe to the respective topic with custom filter options. This will create an alert configuration for the user.

- **getAlertFilterOptions**: A function to get the filter options from the subscribed topic (`Alert` configuration/object).

- **getTopicStackAlerts**: A function to get the subscribed stackable topic. (`Alert` configuration/objects).

> Notifi provides an example project to showcase the usage of the Notifi React Context through this [Example.](https://github.com/notifi-network/notifi-sdk-ts/tree/main/packages/notifi-card-modal-example)  
> For more comprehensive information, please refer to the [notifi-dapp-example.](https://github.com/notifi-network/notifi-sdk-ts/tree/main/packages/notifi-dapp-example)

<br></br>

## **NotifiHistoryContext**

Check or manipulate the notification history of the connected users' account.

_Example_

```tsx
import { useNotifiHistoryContext } from '@notifi-network/notifi-react';

export const MyComponent = () => {
  const {
    isLoading,
    error,
    getHistoryItems,
    markAsRead,
    historyItems,
    unreadCount,
    hasNextPage,
  } = useNotifiHistoryContext();

  // Other code ...
};
```

**Input props**

- **notificationCountPerPage** (Optional): The number of notifications per fetch in the notification history. The default value is `20`.
- **unreadCountScope** (Optional): The scope can be `card` or `tenant`. The default value is `card`.

**Methods**

- **getHistoryItems**: A function to get the notification history items. This method will update the `historyItems` state. It takes `(initialLoad?: boolean)` as input arguments. If `initialLoad` is `true`, it will clean the existing `historyItem` and fetch the first page of the notification history items. If `initialLoad` is `undefined` or `false`, it will fetch the next page from an existing page cursor. You can use `hasNextPage` to check if there are more pages to fetch.

- **markAsRead**: A function to mark all or particular notification items as read. it takes`(ids?: string[])` as input. If `ids` is not provided, it will mark all the items as read.
- **historyItems**: The Notification History Items.
- **unreadCount**: An integer variable representing the unread notification count in `historyItems`.
- **hasNextPage**: A boolean variable to check if there is more page to fetch. If `true`, calling `getHistoryItems()` will fetch the next page.

> **NOTE:**
> page counts are set to 20 by default. You can change the page count by setting the `notificationCountPerPage` in the `<NotifiContextProvider />`or `<NotifiHistoryContextProvider />` Property.
> [See an Example.](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-react-example-v2/src/context/NotifiContextWrapper.tsx#L121)

<br> <br>

# Migrate Your Card

#### Migrate from `@notifi-network/notifi-react-card` (v0.) to `@notifi-network/notifi-react` (v1.)

##### _`@notifi-network/notifi-react` is a major upgrade of `@notifi-network/notifi-react-card`. `@notifi-network/notifi-react` which provides more advanced features by adopting the new Notifi infrastructure (called `fusion`)._

<br> <br>

#### Migrating to `@notifi-network/notifi-react` will have the following benefits:

- **Optimized bundle size**: the package size reduction of ~20%.
- **Better efficiency and performant**: the network request are reduced by ~50%.
- **Better UI & UX**: The new UI/UX design is more user-friendly, intuitive, and customizable.
- **Advanced new features**: support Notifi Admin Portal V2 new features. Check out Notifi Admin Portal V2 [here](https://admin.notifi.network/) for more information.

> **IMPORTANT** `@notifi-network/notifi-react-card` will no longer be maintained. Please use the `@notifi-network/notifi-react` if you are new to the Notifi React SDK.
> For any existing Dapps utilizing `@notifi-network/notifi-react-card`, follow the migration guide below.

<br> </br>

## Migration Guide

As `@notifi-network/notifi-react` is a separate package from `@notifi-network/notifi-react-card`, new package installation is required.

```json
// package.json
{
  // ...
  "dependencies": {
    "@notifi-network/notifi-frontend-client": "^1.0.0",
    "@notifi-network/notifi-graphql": "^1.0.0",
    "@notifi-network/notifi-react": "^1.0.0"
  }
  // ...
}
```

<br> </br>

### Step 1: Replace the `NotifiContext` with the `NotifiContextProvider`

Many of input props of the `NotifiContextProvider` are the same as `NotifiContext`. Differences are highlighted below.
<br> </br>

**Deprecated props**

- `alertConfigurations`_(Optional)_ is deprecated. (No longer needed)
- `keepSubscriptionData` _(Optional)_ is deprecated. (No longer needed)
- `multiWallet` _(Optional)_ is deprecated. (No longer needed)
- `isUsingFrontendClient` _(Optional)_ is deprecated. (No longer needed)

**Newly added props**

- `tenantId` **(Required)**: The `tenantId` or `dAppID` (as referenced on the Admin Portal) property originally was set in the `NotifiSubscriptionCard` component as `dappAddress`. Now it is moved to context provider level.

- `cardId` **(Required)**: The `cardId` property originally was set in the `NotifiSubscriptionCard` component. Now it is moved to context provider level.

- `notificationCountPerPage` _(Optional)_: The `notificationCountPerPage` property is used to set the number of notifications per fetch in the notification history. The default value is `20`.

- `toggleTargetAvailability` _(Optional)_: The `toggleTargetAvailability` property is used to enable/disable the target availability feature. The default value depends on the active destinations set in the Notifi Admin Portal. Additional infromation can be found [here.](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-react/lib/context/NotifiTargetContext.tsx#L82)

<br> </br>

### Step 2: Replace the `<NotifiSubscriptionCard />` with the `<NotifiCardModal />`

Most of the props of `NotifiCardModal` are the same as `NotifiSubscriptionCard`. The only differences are listed below:
<br> </br>

**Deprecated props**

- `loadingSpinnerSize` _(Optional)_ is deprecated. (No longer needed as we can utilize css overrides to customize the spinner size)

- `loadingSpinnerColor` _(Optional)_ is deprecated. (No longer needed as we can utilize css overrides to customize the spinner color)

- `cardId` _(Optional)_ is deprecated. (No longer needed as we can set the `cardId` in the `NotifiContextProvider`)

- `inputLabels` and `inputSeparators` _(Optional)_ is deprecated. Instead, we can use the `copy` prop to customize the input labels. [Seen Here](customizing-the-card-copy)

> Examples Found In [`@notifi-network/notifi-react-example-v2`](https://github.com/notifi-network/notifi-sdk-ts/blob/main/packages/notifi-react-example-v2/src/app/notifi/components-example/page.tsx#L19)

**On-going:** (SUBJECT TO CHANGES)

- `disclosureCopy` (Optional): Not supported yet. but it is planned to be removed and make use of the `copy` prop instead (TBD)

- `onClose` (Optional)

<br></br>

### Step 3 Restyle the card by using the css override

Component layout has significant changes, and accordingly the css classes of the `NotifiCardModal` are also changed. If you are already using the existing `NotifiSubscriptionCard` with the global css override, you will need to deprecate all the css classes and re-implement the new global css override.
For more detail about CSS classes, please refer to the [source code.](https://github.com/notifi-network/notifi-sdk-ts/tree/main/packages/notifi-react/lib/style)

<br></br>

### Step 4: Remove all the related code of the `@notifi-network/notifi-react-card`

- Remove the `@notifi-network/notifi-react-card` package from the `package.json` file.

- Remove the `NotifiSubscriptionCard` component from the codebase.

- Remove the `NotifiContext` component from the codebase.

- Remove the legacy css override related to the `NotifiSubscriptionCard`.