React
The @rising-tide/ui/react entry point - React Query provider and data fetching hooks.
@rising-tide/ui/react provides React Query integration for the protocol API. All hooks pre-shaped against the substrate (SmartProduct, ProductInstance, ProductType, StyleSet) so client apps consume one canonical model.
Setup
Wrap your app with RisingTideProvider (also re-exported as RisingTideQueryProvider) and bring your own QueryClientProvider. The SDK provider holds a RisingTideSDK instance in context; the QueryClient is whatever you configure. ProtocolUserProvider takes the SDK client and a config with three required members, and needs Privy's provider above it to sign anyone in - the shape below is the hand-assembled one; most apps use RisingTideProviders instead:
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RisingTideProvider } from "@rising-tide/ui/react";
import { ProtocolUserProvider } from "@rising-tide/ui/auth";
import { rtClient } from "@/lib/sdk/client";
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 30_000 } },
});
const sdkConfig = {
baseUrl: process.env.NEXT_PUBLIC_RT_API_URL!,
apiKey: process.env.NEXT_PUBLIC_API_KEY,
};
export default function Providers({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<RisingTideProvider config={sdkConfig}>
<ProtocolUserProvider
sdk={rtClient}
config={{ storagePrefix: "myapp", linkInviteCodes: true, onSignupComplete: () => {} }}
>
{children}
</ProtocolUserProvider>
</RisingTideProvider>
</QueryClientProvider>
);
}RisingTideProvider takes a config: RisingTideConfig prop and instantiates the SDK internally - it does not accept a pre-built client. Mount ProtocolUserProvider from @rising-tide/ui/auth for useProtocolUser; the address-keyed hooks (useUserProfile, the aggregate hooks) read only the SDK context.
Hook families
- Smart productsuseSmartProducts, useSmartProduct, useSmartProductContributions
- InstancesuseProductInstances, useProductInstance, useUserInstances
- CataloguseProductTypes, useProductType, useStyleSets, useStyleSet
- MoneyuseFundingGroups, useFundingGroup
- UseruseUserByAddress, useUserSupporting, useUserCollectors
- WalletuseWalletBalance, useTokenPrices, useTestnetFaucet - argument-driven, no SDK context needed
- AggregatesuseUserProfile, useUserRevenue, useUserFeed, useAppTrending
- InvitesuseInvites, useInvitePreview
- Commands and mutationsuseCommand, useDeployProduct, useUploadUserAvatar
All read hooks return { data, isLoading, error, refetch } from React Query, and data is the SDK's ApiResponse envelope. The event and listing mutations (useCreateEvent, useUpdateEvent, useDeleteEvent, useListProductOnApps, useRemoveProductListing) return the standard React Query useMutation shape. useCommand, useDeployProduct, useUploadFile, useUploadUserAvatar and useCreateUser are not built on React Query and return their own shapes - see Hooks.
Components
The entry point also ships a few presentational components. Most take a render prop so they can fit your design system.
| Component | What it does |
|---|---|
PriceDisplay, PriceDisplayPair | A base-unit amount with its currency and an optional usdPrice gloss. An sBTC amount always reads in sats (formatSbtcDisplay), however large; with showCurrency={false} the unit is stripped |
ConnectWalletButton | Sign-in and connected-wallet button driven by props; shows the connected bitcoin (L1) balance in sats |
RevenueSplitItem, RevenueSplitsDisplay | A contribution row, and the list of a product's revenue split |
EventStatusBadge, PageStatusBadge, TransactionStatusBadge, PaymentStatusBadge, ReservationStatusBadge | A status with its colour classes (getEventStatusClasses and its siblings return the classes alone) |
StickerPicker, StickerEditor | Choose a sticker, and place it inside a style's sticker zone |
CopyButton, ThemeToggle | Copy to clipboard (over useClipboard), and a light/dark switch (over useTheme) |