React hooks and utils for de[id]
@dustlabs/profiles is a collection of React hooks and utils containing everything you need to start integrating de[id] into your frontend, from components to chain-specific support. It makes it easy to "Sign In," display profile data and holdings, add wallets, interact with the de[id] backend, and much more.
yarn add @dustlabs/profiles @dustlabs/web framer-motionOverview
import { WagmiConfig, createConfig, mainnet } from 'wagmi'
import { createPublicClient, http } from 'viem'
import { DeIdProvider } from "@dustlabs/profiles/core";
import { DeIdEvm } from "@dustlabs/profiles/evm";
import { RainbowKitProvider } from "@rainbow-me/rainbowkit";
const config = createConfig({
autoConnect: true,
publicClient: createPublicClient({
chain: mainnet,
transport: http()
}),
})
function App() {
return (
<WagmiConfig config={config}>
<RainbowKitProvider chains={[mainnet]}>
<DeIdEvm api="https://your.de.id.backend.endpoint">
{(providerProps) => (
<DeIdProvider {...providerProps}>
<Profile />
</DeIdProvider>
)}
</DeIdEvm>
</RainbowKitProvider>
</WagmiConfig>
)
}import { useDeId } from "@dustlabs/profiles/hooks";
import { ProfileButton } from "@dustlabs/profiles/evm";
function Profile() {
const { isSignedIn, signIn, signOut, profile } = useDeId();
if (isSignedIn)
return (
<div>
Signed in to {profile.profileId}
<button onClick={() => signOut()}>Sign Out</button>
</div>
)
return (
<div>
<ProfileButton />
<button onClick={() => signIn()}>Sign In</button>
</div>
)
}In this example, we add de[id] to an exisitng EVM project, using the DeIdEvm adapter to pass providerProps into the DeIdProvider React Context. The provider props is set up to use EVM's wallet data to initialize de[id].
Next, we let the user connect their wallet using the <ProfileButton />, and use the signIn function from the useDeId hook to sign in to the app. Finally, we show the connected profile's profile ID with profile field in useDeId and allow them to sign out with signOut.
Features
This SDK supports all these features out-of-the-box:
- Hooks for querying profiles and mutating, adding and removing wallets, socials, email, etc.
- Built-in wallet connect components extending on rainbowkit to connect EVM wallets.
- Support for adding BTC and Solana wallets to de[id].
- Full authentication flow and handling via the
DeIdProviderReact Context. - TypeScript ready gql schema.
- Out-of-box React components for displaying and editing profile data.
...and a lot more.
Contribution Guide
There are a few guiding principles behind the way this project is structured. If you are contributing to this repository, it will be useful to keep these in mind.
Context Segregation
Due to how bundling works in JavaScript, React context cannot be read by a component that is in another subfolder.
As such, you might see differences in the way context is being passed to components. Since the main core context drives this SDK,
it lives in the /core subfolder. As such, all components in the /evm subfolder for instance, will be unable to read the context directly.
Hence, the components inside these subfolders take in the context as a parameter, and access it from there. Take for example, the difference between
the DeIdAvatar component from /core and the ProfileButton component from /evm.
import { useDeId, useDeIdModal } from "@dustlabs/profiles/core";
import { ProfileButton } from "@dustlabs/profiles/evm";
function App() {
const deId = useDeId();
const deIdModal = useDeIdModal();
return <ProfileButton deId={deId} deIdModal={deIdModal} />
}Here, you can see that ProfileButton requires to take in the deId and deIdModal context as parameters, which then allows the component to access the context.
In contrast, the DeIdAvatar component does not require this, and can call useDeId directly in the component's code.
import { DeIdAvatar } from "@dustlabs/profiles/core";
function App() {
return <DeIdAvatar />
}If you are confused, just look at which folder is your component in. If it is in /core, you can use the context directly in the code. If you component exists outside the /core package,
then make sure you take in the relevant contexts you need as parameters.
Dependency Segregation
When creating components and hooks, keep in mind that the /core package is to be free of chain-specific dependencies.
The reason is because we do not want the importing application to have to install dependencies from a chain that they are not utilizing.
EVM projects should only need to install EVM packages, not Solana packages.
If you find yourself having to deal with chain-specific logic, make sure you do so in the respective
subfolders such as /evm or /btc. If you look closely, you can also see that this is the reason why we rely on
adapter wrappers to pass wallet specific data into DeIdContext. This lets us use wallet data without explicitly importing these dependencies inside
the /core subfolder. The drawback is that for each chain, we need to clean up the parameters within the specific adapter function before passing it to
DeIdContext (as providerProps) so the type structure stays the same throughout all supported chains.
As of now we only support the EVM adapter DeIdEvm to manage global wallet states since all our first-party websites are EVM-based websites. In the future if the need arises, we can add adapters for other chains such as BTC and SOL.
The params passed from adapters into DeIdContext have the type BaseParams, which contains generic wallet data.
address
string | undefined
The connected wallet's address.
isConnected
boolean
Whether a wallet is connected to the application.
profileParams
ProfileParams
The current wallet's address and network used for profile querying, of type ProfileParams.
verifyParams
VerifyParams
Utility functions of type VerifyParams for verifying wallet ownership, such as in useVerifyEvmWallet.
handleChangeProfileParams
(profileParams: ProfileParams) => void
A function to update profileParams.
Reach out to Leonard if you have any questions on how to contribute to this project.