@notifi-network/notifi-react
v8.0.0
Published
React components to access Notifi core services
Readme
Notifi React SDK
@notifi-network/notifi-react accelerates the development of Notifi integrated dapps.
- Out of The Box Implementation
- Customized Implementation
- Custom Integration
- Migrating from an older version of the SDK
Play around with a Card Example
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
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
Mount the NotifiCardModal to your dApp
Prerequisites (IMPORTANT)
- To use
NotifiCardModal, you need to wrap your component withNotifiContextProviderfirst. - Notifi supports both
on-chainandoff-chainauthentication. The authentication method differs based on theLoginParamsWithUserParamstype passed to theNotifiContextProvider.- For
on-chainauthentication,walletBlockchain='<blockchain>',signMessagecallback function, and the respectivewallet keys or addressesfor theblockchainare required. The common EVM blockchain example is shown above. - For
off-chainauthentication,walletBlockchain='OFF_CHAIN',signIncallback function, anduserAccountare required.userAccountcan be any user-related unique identifier derived from a JWT token. The Google off-chain OIDC authentication example is shown below.
- For
Example Quick Start for Ethereum (On chain)
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)
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
- Notifi supported blockchains: WalletBlockchain Enum document
- Notifi supported OIDC providers: OidcProvider Enum document
- To enable OIDC login, it requires additional setup to integrate your OIDC provider with Notifi tenant using Notifi Admin Portal check on the Notifi Documentation (WIP: coming soon)
Customize NotifiCardModal component
NotifiCardModal is fully customizable using global CSS overrides and optional properties.
Global CSS overrides
By overriding the default CSS classes, we can style the elements in the card. Default CSS Classes are found here.
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
import '@notifi-network/notifi-react/dist/index.css';
- Make sure this import is placed at the top level of the component file. complete example Find the overrideable CSS classes here
Other Optional Properties
NotifiCardModal component provides the following additional optional properties to customize the card even further:
Check out the NotifiCardModalProps type documentation to know more details
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
<NotifiCardModal darkMode />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
// ...
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.
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 to know more details
Common Example: Customizing the Connect view footer
Connect view footer preview as seen below:
Example code
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
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 to know the className customizable components.
Example
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} />
{/* ... */}
</>
);
};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.
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
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.
import {
NotifiFrontendClientProvider,
NotifiTenantConfigProvider,
} from '@notifi-network/notifi-react';
const App = () => {
const params = {
// params for contexts
};
return (
<NotifiFrontendClientProvider {...params}>
<NotifiTenantConfigProvider {...params}>
<MyComponent />
</NotifiTenantConfigProvider>
</NotifiFrontendClientProvider>
);
};NotifiFrontendClientContext
Provides the Notifi Frontend Client and the user authentication status.
Example
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
loginViaTransactionproperty is used to achieve this feature.Step1: Wrap higher (top) level of dapp components with
<NotifiContextProvider>(or<NotifiFrontendClientProvider>). Step2: put theloginViaTransaction.nonceas memo when user signs a transaction. Step3: Pass in the signature fromStep#2to theloginViaTransaction.loginmethod.Case 1: Plain transaction
// 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
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 longerror in this case.
- 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
NotifiTenantConfigContext
Provides the tenant configuration.
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.
- inputs:
inputis a concept which is used when a dynamic topic subscription value needs to be adopted. Theinputis a key-value pair object. The key is the value associated with theCreate a new topicsection 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 interface.
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.

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 setfarmin Admin portal UX inUser Selects From Listsection. And we want to allow to haveBTC/ETH farmandBTC/USDT farm, we can set theinputsobject to{ farm: [{label: 'BTC/ETH farm', value: 'BTC-ETH'}, {label: 'BTC/USDT farm', value: 'BTC-USDT'}] }. Thevalueis the value that will be passed to the topic subscription.
NOTE the
valuein theInputObjectshould associate with the subscription value in the parser.labelis the display name in the UI.
NotifiUserSettingContext
Provides user specific methods and state.
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.
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:
- Telegram
- SMS
- Discord
- Slack
- Want another destination? Email Us
Example
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.
targetGroupis 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
singleTargetRenewArgsas an argument. NOTE: This action does not require updatingtargetInputsmanually.targetInputswill be updated automatically oncerenewTargetGroupis called successfully. - Update all targets: all targets will be updated according to the
targetInputsstate w/o passing any argument.
- Update single target: passing
TargetGroupId: The target group id which is the argument to call
renewTargetGroupfunction.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
NotifiContextProviderWalletTargetPlugincontext in@notifi-network/notifi-react-wallet-target-pluginif Target.wallet.isAvailable is set totrue. For more details, refer to@notifi-network/notifi-react-wallet-target-pluginREADME.
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
Alertobject associated to the users with the respective topic. Additional Information.
Example
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 (
Alertconfiguration/object).getTopicStackAlerts: A function to get the subscribed stackable topic. (
Alertconfiguration/objects).
Notifi provides an example project to showcase the usage of the Notifi React Context through this Example.
For more comprehensive information, please refer to the notifi-dapp-example.
NotifiHistoryContext
Check or manipulate the notification history of the connected users' account.
Example
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
cardortenant. The default value iscard.
Methods
getHistoryItems: A function to get the notification history items. This method will update the
historyItemsstate. It takes(initialLoad?: boolean)as input arguments. IfinitialLoadistrue, it will clean the existinghistoryItemand fetch the first page of the notification history items. IfinitialLoadisundefinedorfalse, it will fetch the next page from an existing page cursor. You can usehasNextPageto 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. Ifidsis 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, callinggetHistoryItems()will fetch the next page.
NOTE: page counts are set to 20 by default. You can change the page count by setting the
notificationCountPerPagein the<NotifiContextProvider />or<NotifiHistoryContextProvider />Property. See an Example.
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).
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 for more information.
IMPORTANT
@notifi-network/notifi-react-cardwill no longer be maintained. Please use the@notifi-network/notifi-reactif you are new to the Notifi React SDK. For any existing Dapps utilizing@notifi-network/notifi-react-card, follow the migration guide below.
Migration Guide
As @notifi-network/notifi-react is a separate package from @notifi-network/notifi-react-card, new package installation is required.
// 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"
}
// ...
}
Step 1: Replace the NotifiContext with the NotifiContextProvider
Many of input props of the NotifiContextProvider are the same as NotifiContext. Differences are highlighted below.
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): ThetenantIdordAppID(as referenced on the Admin Portal) property originally was set in theNotifiSubscriptionCardcomponent asdappAddress. Now it is moved to context provider level.cardId(Required): ThecardIdproperty originally was set in theNotifiSubscriptionCardcomponent. Now it is moved to context provider level.notificationCountPerPage(Optional): ThenotificationCountPerPageproperty is used to set the number of notifications per fetch in the notification history. The default value is20.toggleTargetAvailability(Optional): ThetoggleTargetAvailabilityproperty 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.
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:
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 thecardIdin theNotifiContextProvider)inputLabelsandinputSeparators(Optional) is deprecated. Instead, we can use thecopyprop to customize the input labels. Seen Here
Examples Found In
@notifi-network/notifi-react-example-v2
On-going: (SUBJECT TO CHANGES)
disclosureCopy(Optional): Not supported yet. but it is planned to be removed and make use of thecopyprop instead (TBD)onClose(Optional)
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.
Step 4: Remove all the related code of the @notifi-network/notifi-react-card
Remove the
@notifi-network/notifi-react-cardpackage from thepackage.jsonfile.Remove the
NotifiSubscriptionCardcomponent from the codebase.Remove the
NotifiContextcomponent from the codebase.Remove the legacy css override related to the
NotifiSubscriptionCard.
