Typescript libraries and multi-chain modal component created to simplify building cross-chain applications deployed with Valence Protocol. These are the TS equivalent to Valence Domain Clients in Rust. The library supports Ethereum, Solana, and Cosmos.
Libraries are in their early stage. APIs subject to change.
For developer and deployment docs, see docs folder.
Libraries are tree-shakeable, and can be configured to support only the chains and ecosystems the project needs.
Ecosystem-specific tooling is imported as a peer dependency, and valence-protocol-ts provides an optional, loose wrapper to abstract common operations. Signers and wallet info can be accessed with React hooks. Detailed explanation below.
import {
useSigningSolanaClient,
} from '@valence-protocol/domain-clients-react/solana';
// React component
const solanaSigningClient = useSolanaSigningClient({clusterId:'solana:devent'})
solanaSigningClient.getSolBalance({...})
solanaSigningClient.transfer({...})| Package | Version | Downloads | Description |
|---|---|---|---|
@valence-protocol/domain-clients-core |
Core TypeScript client library for interacting with domain APIs | ||
@valence-protocol/domain-clients-react |
React hooks and context providers for domain client logic | ||
@valence-protocol/domain-modal-react |
Reusable React modal component library for Valence apps |
- Install valence-protocol dependencies
pnpm install @valence-protocol/domain-clients-core @valence-protocol/domain-clients-react @valence-protocol/domain-modal-react
pnpm install @tanstack/react-query ## general peer dependency- Install peer dependencies You will need to install the required libraries for the ecosystem you would like to support.
# for EVM
pnpm install wagmi viem
# for Solana
pnpm install gill @wallet-ui/react ws
## note: when interacting with frameworks that have not moved to @solana/kit (used by gill under the hood and importable through gill), you may need to also install @solana/web3.js and @solana/compat
## ws is optional if you do not want to use the websocket features in gill/solana kit
# for Cosmos
pnpm install grazWith graz, you will also need to add a post-install script to generate chain info locally. The generated chain infos will not be packaged with your app unless you import them.
{
"scripts": {
"postinstall": "pnpm gen:cosmos",
"gen:cosmos": "graz generate -g"
}
}- Define config. Use the example app config files as a template. Only include the domains and chains you would like to support in your project.
Example of the root config:
import { DomainClientsConfig } from '@valence-protocol/domain-clients-react';
export const domainClientsConfig: DomainClientsConfig = {
evm: evmConfig,
cosmos: cosmosConfig,
solana: solanaConfig,
};- Wrap your app root in a
DomainModalProviderandReactQueryProviderFor Next.js 14+, you will need to wrap the providers in a client component.
// AppProvider.tsx (for Next.js 14+)
'use client'
import { domainClientsConfig } from '@/config';
import { DomainModalProvider } from '@valence-protocol/domain-modal-react';
export const AppProviders = ({ children }: { children: React.ReactNode }) => {
return (
<...OtherProviders>
<ReactQueryProvder {...queryClient}> // TODO: link docs for setting this up
<DomainModalProvider config={domainClientsConfig}>
{children}
</DomainModalProvider>
</ReactQueryProvider>
<...OtherProviders>
);
};- Import css
// layout.tsx (for Next.js) or similar application root
import '@valence-protocol/domain-modal-react/styles.css';
const Root = () => {
...
return (
<AppProviders>
{children}
</AppProviders>
);
};- Open the modal with
showModal
import { useDomainModal } from '@valence-protocol/domain-modal-react';
const { showModal } = useDomainModal();Pure-JS code that abstract common, implementation-specific methods. There are a few pre-built operations (such as transferring tokens and reading balances). To do anything not pre-built, you can call getClient on the respective client and perform anything you need. Commonly used patterns will be added as client functions over time.
Imports per-domain are tree-shakeable. For example:
import { EvmClient } from '@valence-protocol/domain-clients-core/evm';React hooks and context provider to access the config and use domain clients in a react app.
The imports per-domain are tree-shakeable. For example:
import {
useSigningSolanaClient,
} from '@valence-protocol/domain-clients-react/solana';
// React component
const solanaSigningClient = useSolanaSigningClient({clusterId:'solana:devent'})
solanaSigningClient.getSolBalance({...})
solanaSigningClient.transfer({...})A React UI component and context provider that allows you to manage wallet connections across multiple domains. It is a loose wrapper around domain-specific UI libraries. Based on the domain clients configuration, it will render the appropriate wallet modal.
The modal will omit dependencies for ecosystems excluded from in the configuration.
Please reference the example app, but here are some basics:
See server/ in the example app for more exmaples.
import { domainClientsConfig } from '@/config/domainClientsConfig';
import { EvmClient } from '@valence-protocol/domain-clients-core/evm';
import { type Address, erc20Abi } from 'viem';
const evmClient = new EvmClient({
config: config.wagmiConfig,
chainId,
});
const balance = await evmClient.queryErc20Balance({
contractAddress: erc20Address,
address,
});If your app is wrapped in the DomainClientsProvider, you can simply call useXSigningClient and useXClient to access these via hook. You will need to specify which chain you want to target, and it will use the rpc in your config file.
import {
useSolanaClient,
useSigningSolanaClient,
useCosmosClient,
useSigningCosmosClient,
useEvmClient,
useSigningEvmClient,
} from '@valence-protocol/domain-clients-react';
const solananClient = useSolanaClient({ clusterId });
const signingSolanaClient = useSigningSolanaClient({ clusterId });
const cosmosClient = useCosmosClient({ chainId });
const signingCosmosClient = useSigningCosmosClient({ chainId });
const evmClient = useEvmClient({ chainId });
const signingEvmClient = useSigningEvmClient({ chainId });!!! FYI: Due to to a quirk with the Solana wallet library, you can only instantiate useSigningSolanaClient if a solana wallet is already connected. Otherwise it will crash your app. The short-term workaround is to only instantiate the hook within an "account guard".
import { useWalletUiAccount } from '@wallet-ui/react'; // solana wallet toolings
export const SolanaAccountGuard = ({
children,
fallback,
}: {
children: React.ReactNode;
fallback: React.ReactNode;
}) => {
const { account } = useWalletUiAccount();
if (!account) {
return fallback;
}
return <>{children}</>;
};You can also access the config with
const config = useDomainConfig();Use various domain-specific hooks and utils as needed. They will work as expected because we render their providers under the hod. The implementation and naming for each varies. You can find some examples of how these are used in the example app, but it is suggested to consult the individual docs.
import { useAccount as useEvmAccount } from 'wagmi';
import { useAccount as useCosmosAccount } from 'graz';
import { useWalletUi as useSolanaAccount } from '@wallet-ui/react';Feel free to raise issues, or contact the team on Telegram.
