Towns 백서

Towns

원문

bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 17쪽 중 6쪽

col/towns/blob/main/packages/react-sdk/src/useMyMember.ts) ## Parameters ### streamId * **Type:** `string` The id of the stream to set the ENS address of. ### config * **Type:** `ActionConfig<Myself["setEnsAddress"]>` * **Optional** Configuration options for the action. ## Return Type The `setEnsAddress` action and its loading state. ```ts theme={null} { data: void | undefined; error: Error | undefined; isPending: boolean; isSuccess: boolean; isError: boolean; setEnsAddress: (ensAddress: `0x${string}`) => Promise<void>; } ``` # useSetNft Source: https://docs.towns.com/build/react-sdk/api/useSetNft Hook to set the NFT of the current user in a stream. You should be validating if the NFT belongs to the user before setting it. ## Imports ```ts theme={null} import { useSetNft } from '@towns-protocol/react-sdk' ``` ## Definition ```ts theme={null} function useSetNft( streamId: string, config?: ActionConfig<Myself["setNft"]>, ): { data: void | undefined; error: Error | undefined; isPending: boolean; isSuccess: boolean; isError: boolean; setNft: (nft: NftModel) => Promise<void>; } ``` **Source:** [useSetNft](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useMyMember.ts) ## Parameters ### streamId * **Type:** `string` The id of the stream to set the NFT of. ### config * **Type:** `ActionConfig<Myself["setNft"]>` * **Optional** Configuration options for the action. ## Return Type The `setNft` action and its loading state. ```ts theme={null} { data: void | undefined; error: Error | undefined; isPending: boolean; isSuccess: boolean; isError: boolean; setNft: (nft: NftModel) => Promise<void>; } ``` # useSetUsername Source: https://docs.towns.com/build/react-sdk/api/useSetUsername Hook to set the username of the current user in a stream. ## Imports ```ts theme={null} import { useSetUsername } from '@towns-protocol/react-sdk' ``` ## Definition ```ts theme={null} function useSetUsername( streamId: string, config?: ActionConfig<Myself["setUsername"]>, ): { data: void | undefined; error: Error | undefined; isPending: boolean; isSuccess: boolean; isError: boolean; setUsername: (username: string) => Promise<void>; } ``` **Source:** [useSetUsername](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useMyMember.ts) ## Parameters ### streamId * **Type:** `string` The id of the stream to set the username of. ### config * **Type:** `ActionConfig<Myself["setUsername"]>` * **Optional** Configuration options for the action. ## Return Type The `setUsername` action and its loading state. ```ts theme={null} { data: void | undefined; error: Error | undefined; isPending: boolean; isSuccess: boolean; isError: boolean; setUsername: (username: string) => Promise<void>; } ``` # useSpace Source: https://docs.towns.com/build/react-sdk/api/useSpace Hook to get data about a space. You can use this hook to get space metadata and ids of channels in the space. ## Imports ```ts theme={null} import { useSpace } from '@towns-protocol/react-sdk' ``` ## Examples You can use this hook to display the data about a space: ```tsx theme={null} import { useSpace } from '@towns-protocol/react-sdk' const Space = ({ spaceId }: { spaceId: string }) => { const { data: space } = useSpace(spaceId) return <div>{space.metadata?.name || 'Unnamed Space'}</div> } ``` ## Definition ```ts theme={null} function useSpace( spaceId: string, config?: ObservableConfig.FromObservable<Space>, ): ObservableValue<SpaceModel> ``` **Source:** [useSpace](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useSpace.ts) ## Parameters ### spaceId * **Type:** `string` The id of the space to get data about. ### config * **Type:** `ObservableConfig.FromObservable<Space>` * **Optional** Configuration options for the observable. ## Return Type The SpaceModel data. ```ts theme={null} ObservableValue<SpaceModel> ``` # useSyncAgent Source: https://docs.towns.com/build/react-sdk/api/useSyncAgent Hook to get the sync agent from the TownsSyncProvider. You can use it to interact with the sync agent for more advanced usage. Throws an error if no sync agent is set in the TownsSyncProvider. ## Imports ```ts theme={null} import { useSyncAgent } from '@towns-protocol/react-sdk' ``` ## Definition ```ts theme={null} function useSyncAgent(): SyncAgent ``` **Source:** [useSyncAgent](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useSyncAgent.tsx) ## Return Type The sync agent in use, set in TownsSyncProvider. ```ts theme={null} SyncAgent ``` # useThreads Source: https://docs.towns.com/build/react-sdk/api/useThreads Hook to get the threads from a stream. ## Imports ```ts theme={null} import { useThreads } from '@towns-protocol/react-sdk' ``` ## Definition ```ts theme={null} function useThreads( streamId: string, config?: ObservableConfig.FromObservable<TimelinesMap>, ): ObservableValue<TimelinesMap> ``` **Source:** [useThreads](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useThreads.ts) ## Parameters ### streamId * **Type:** `string` The id of the stream to get the threads from. ### config * **Type:** `ObservableConfig.FromObservable<TimelinesMap>` * **Optional** Configuration options for the observable. ## Return Type The threads of the stream as a map from the message eventId to a thread. ```ts theme={null} ObservableValue<TimelinesMap> ``` # useTimeline Source: https://docs.towns.com/build/react-sdk/api/useTimeline Hook to get the timeline events from a stream. You can use the `useTimeline` hook to get the timeline events from a channel stream, dm stream or group dm stream ## Imports ```ts theme={null} import { useTimeline } from '@towns-protocol/react-sdk' ``` ## Examples ```ts theme={null} import { useTimeline } from '@towns-protocol/react-sdk' import { RiverTimelineEvent } from '@towns-protocol/sdk' const { data: events } = useTimeline(streamId) // You can filter the events by their kind const messages = events.filter((event) => event.content?.kind === RiverTimelineEvent.ChannelMessage) ``` ## Definition ```ts theme={null} function useTimeline( streamId: string, config?: ObservableConfig.FromObservable<TimelineEvent[]>, ): ObservableValue<TimelineEvent[]> ``` **Source:** [useTimeline](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useTimeline.ts) ## Parameters ### streamId * **Type:** `string` The id of the stream to get the timeline events from. ### config * **Type:** `ObservableConfig.FromObservable<TimelineEvent[]>` * **Optional** Configuration options for the observable. ## Return Type The timeline events of the stream as an observable. ```ts theme={null} ObservableValue<TimelineEvent[]> ``` # useTowns Source: https://docs.towns.com/build/react-sdk/api/useTowns Hook to get an observable from the sync agent. An alternative of our premade hooks, allowing the creation of custom abstractions. ## Imports ```ts theme={null} import { useTowns } from '@towns-protocol/react-sdk' ``` ## Definition ```ts theme={null} function useTowns<T>( selector: (sync: SyncSelector) => Observable<T>, config?: ObservableConfig.FromData<T>, ): ObservableValue<T extends PersistedModel<infer UnwrappedData> ? UnwrappedData : T> ``` **Source:** [useTowns](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useTowns.ts) ## Parameters ### selector * **Type:** `(sync: SyncSelector) => Observable<T>` A selector function to get a observable from the sync agent. ### config * **Type:** `ObservableConfig.FromData<T>` * **Optional** Configuration options for the observable. #### config.fireImmediately * **Type:** `boolean` * **Optional** Trigger the update immediately, without waiting for the first update. #### config.onError * **Type:** `(error: Error) => void` * **Optional** Callback function to be called when an error occurs. #### config.onUpdate * **Type:** `(data: Data) => void` * **Optional** Callback function to be called when the data is updated. ## Return Type The data from the selected observable. ```ts theme={null} ObservableValue<T extends PersistedModel<infer UnwrappedData> ? UnwrappedData : T> ``` # useTownsAuthStatus Source: https://docs.towns.com/build/react-sdk/api/useTownsAuthStatus Hook to get the auth status of the user connection with the Towns network. ## Imports ```ts theme={null} import { useTownsAuthStatus } from '@towns-protocol/react-sdk' ``` ## Definition ```ts theme={null} function useTownsAuthStatus( config?: ObservableConfig.FromObservable<AuthStatus>, ): { status: AuthStatus; isInitializing: boolean; isEvaluatingCredentials: boolean; isCredentialed: boolean; isConnectingToTowns: boolean; isConnectedToTowns: boolean; isDisconnected: boolean; isError: boolean; } ``` **Source:** [useTownsAuthStatus](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useTownsAuthStatus.ts) ## Parameters ### config * **Type:** `ObservableConfig.FromObservable<AuthStatus>` * **Optional** Configuration options for the observable. ## Return Type An object containing the current AuthStatus status and boolean flags for each possible status. ```ts theme={null} { status: AuthStatus; isInitializing: boolean; isEvaluatingCredentials: boolean; isCredentialed: boolean; isConnectingToTowns: boolean; isConnectedToTowns: boolean; isDisconnected: boolean; isError: boolean; } ``` # useUserDms Source: https://docs.towns.com/build/react-sdk/api/useUserDms Hook to get the direct messages of the current user. ## Imports ```ts theme={null} import { useUserDms } from '@towns-protocol/react-sdk' ``` ## Examples You can combine this hook with the `useDm`, `useMemberList` and `useMember` hooks to get all direct messages of the current user and render them, showing the name of the other user in the dm: ```tsx theme={null} import { useDm, useMyMember, useMemberList, useMember } from '@towns-protocol/react-sdk' const AllDms = () => { const { streamIds } = useUserDms() return <>{streamIds.map((streamId) => <Dm key={streamId} streamId={streamId} />)}</> } const Dm = ({ streamId }: { streamId: string }) => { const { data: dm } = useDm(streamId) const { userId: myUserId } = useMyMember(streamId) const { data: members } = useMemberList(streamId) const { userId, username, displayName } = useMember({ streamId, // We find the other user in the dm by checking the userIds in the member list // and defaulting to the current user if we don't find one, since a user is able to send a dm to themselves userId: members.userIds.find((userId) => userId !== sync.userId) || sync.userId, }) return <span>{userId === myUserId ? 'You' : displayName || username || userId}</span> } ``` ## Definition ```ts theme={null} function useUserDms( config?: ObservableConfig.FromObservable<Dms>, ): { error: Error | undefined; status: "loading" | "loaded" | "error"; isLoading: boolean; isError: boolean; isLoaded: boolean; streamIds: string[]; } ``` **Source:** [useUserDms](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useUserDms.ts) ## Parameters ### config * **Type:** `ObservableConfig.FromObservable<Dms>` * **Optional** Configuration options for the observable. ## Return Type The list of all direct messages stream ids of the current user. ```ts theme={null} { error: Error | undefined; status: "loading" | "loaded" | "error"; isLoading: boolean; isError: boolean; isLoaded: boolean; streamIds: string[]; } ``` # useUserGdms Source: https://docs.towns.com/build/react-sdk/api/useUserGdms Hook to get the group dm streams of the current user. ## Imports ```ts theme={null} import { useUserGdms } from '@towns-protocol/react-sdk' ``` ## Examples You can combine this hook with the `useGdm` hook to get all group dm streams of the current user and render them: ```tsx theme={null} import { useUserGdms, useGdm } from '@towns-protocol/react-sdk' const AllGdms = () => { const { streamIds } = useUserGdms() return <>{streamIds.map((streamId) => <Gdm key={streamId} streamId={streamId} />)}</> } const Gdm = ({ streamId }: { streamId: string }) => { const { data: gdm } = useGdm(streamId) return <div>{gdm.metadata?.name || 'Unnamed Gdm'}</div> } ``` ## Definition ```ts theme={null} function useUserGdms( config?: ObservableConfig.FromObservable<Gdms>, ): { error: Error | undefined; status: "loading" | "loaded" | "error"; isLoading: boolean; isError: boolean; isLoaded: boolean; streamIds: string[]; } ``` **Source:** [useUserGdms](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useUserGdms.ts) ## Parameters ### config * **Type:** `ObservableConfig.FromObservable<Gdms>` * **Optional** Configuration options for the observable. ## Return Type The list of all group dm stream ids of the current user. ```ts theme={null} { error: Error | undefined; status: "loading" | "loaded" | "error"; isLoading: boolean; isError: boolean; isLoaded: boolean; streamIds: string[]; } ``` # useUserSpaces Source: https://docs.towns.com/build/react-sdk/api/useUserSpaces Hook to get the spaces of the current user. ## Imports ```ts theme={null} import { useUserSpaces } from '@towns-protocol/react-sdk' ``` ## Examples You can combine this hook with the `useSpace` hook to get all spaces of the current user and render them: ```tsx theme={null} import { useUserSpaces, useSpace } from '@towns-protocol/react-sdk' const AllSpaces = () => { const { spaceIds } = useUserSpaces() return <>{spaceIds.map((spaceId) => <Space key={spaceId} spaceId={spaceId} />)}</> } const Space = ({ spaceId }: { spaceId: string }) => { const { data: space } = useSpace(spaceId) return <div>{space.metadata?.name || 'Unnamed Space'}</div> } ``` ## Definition ```ts theme={null} function useUserSpaces( config?: ObservableConfig.FromObservable<Spaces>, ): { error: Error | undefined; status: "loading" | "loaded" | "error"; isLoading: boolean; isError: boolean; isLoaded: boolean; spaceIds: string[]; } ``` **Source:** [useUserSpaces](https://github.com/towns-protocol/towns/blob/main/packages/react-sdk/src/useUserSpaces.ts) ## Parameters ### config * **Type:** `ObservableConfig.FromObservable<Spaces>` * **Optional** Configuration options for the observable. ## Return Type The list of all space ids of the current user. ```ts theme={null} { error: Error | undefined; status: "loading" | "loaded" | "error"; isLoading: boolean; isError: boolean; isLoaded: boolean; spaceIds: string[]; } ``` # Changelog Source: https://docs.towns.com/build/react-sdk/changelog # Getting Started Source: https://docs.towns.com/build/react-sdk/getting-started This guide will help you get started with Towns Protocol React SDK. You'll learn how to: 1. [Install the React SDK](#installation) 2. [Set up the necessary providers](#setting-up-providers) 3. [Connect to Towns](#connecting-to-towns-protocol) 4. [Create a space](#creating-a-space) 5. [Send your first message](#sending-your-first-message) ## Installation You can start a new Towns project in two ways: ### Using create-towns-protocol-app (Recommended) The easiest way to get started is using `create-towns-protocol-app` and follow the instructions in the terminal. This will set up a new React project with all the necessary dependencies and configurations. ```bash theme={null} # bun bun create towns-protocol-app my-app # npm npm create towns-protocol-app my-app # yarn yarn create towns-protocol-app my-app # pnpm pnpm create towns-protocol-app my-app ``` By default, this will create a new app using the Towns Playground template - a full-featured example application that demonstrates Towns's Protocol capabilities. ### Manual Installation If you prefer to add the React SDK to an existing project, install the required dependencies: ```bash theme={null} bun add @towns-protocol/react-sdk @towns-protocol/sdk vite-plugin-node-polyfills ``` Then, add the `vite-plugin-node-polyfills` to your `vite.config.ts`: ```ts vite.config.ts {1,9} theme={null} import { nodePolyfills } from 'vite-plugin-node-polyfills' import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ // ...rest of your config plugins: [ // ...rest of your plugins nodePolyfills(), react(), ], }) ``` ## Setting Up Providers Towns requires a few providers to be set up at the root of your application: 1. `WagmiProvider` - For Web3 wallet connection (recommended) 2. `TownsSyncProvider` - For interacting with Towns Protocol Here's how to set them up: ```tsx App.tsx theme={null} import { TownsSyncProvider } from "@towns-protocol/react-sdk"; import { base, baseSepolia } from 'viem/chains' import { WagmiConfig, createConfig } from "wagmi"; import { createPublicClient, http } from 'viem' // Configure Wagmi export const wagmiConfig = createConfig({ autoConnect: true, publicClient: createPublicClient({ chain: [base, baseSepolia], transport: http() }), }) function App() { return ( <WagmiConfig config={wagmiConfig}> <TownsSyncProvider> {/* Your app content */} </TownsSyncProvider> </WagmiConfig> ); } ``` If you need any assistance with setting up Wagmi, check out the [Wagmi Getting Started Guide](https://wagmi.sh/react/getting-started). ## Connecting to Towns Protocol You can connect to Towns using either a Web3 wallet (recommended) or a bearer token. You can use the following networks: * `omega` - The Towns mainnet, uses Base as the EVM chain * `gamma` - The Towns testnet, uses Base Sepolia as the EVM chain We recommend using `gamma` as a starting point. <Note> You can use other gamma clients like [Towns (gamma)](https://app.gamma.towns.com) or the [Towns Playground](https://river-sample-app.vercel.app) to help you inspect messages on the `gamma` network. </Note> ### Using a Web3 Wallet ```tsx theme={null} import { useAgentConnection } from "@towns-protocol/react-sdk"; import { townsEnv } from "@towns-protocol/sdk"; import { getEthersSigner } from "./utils/viem-to-ethers"; import { wagmiConfig } from "./config/wagmi"; const townsConfig = townsEnv().makeTownsConfig("gamma"); function ConnectButton() { const { connect, isAgentConnecting, isAgentConnected } = useAgentConnection(); return ( <button onClick={async () => { const signer = await getEthersSigner(wagmiConfig); connect(signer, { townsConfig }); }} > {isAgentConnecting ? "Connecting..." : "Connect"} {isAgentConnected && "Connected ✅"} </button> ); } ``` <Note> You'll need to use `getEthersSigner` to get the signer from viem wallet client. Towns SDK uses ethers under the hood, so you'll need to convert the viem wallet client to an ethers signer. You can get the `getEthersSigner` function from [Wagmi docs](https://wagmi.sh/core/guides/ethers#usage-1). </Note> ### Using a Bearer Token You can connect to Towns using a pre-existing identity. This allows you to read and send messages, but you won't be able to create spaces or channels (on-chain actions). <Note> If you have a Towns account, you can get your bearer token from there. Type `/bearer-token` in any conversation to get your token. </Note> ```tsx theme={null} import { useAgentConnection } from "@towns-protocol/react-sdk"; import { townsEnv } from "@towns-protocol/sdk"; const townsConfig = townsEnv().makeTownsConfig("gamma"); function ConnectButton() { const { connectUsingBearerToken, isAgentConnecting, isAgentConnected } = useAgentConnection(); const [bearerToken, setBearerToken] = useState(''); return ( <div> <input value={bearerToken} onChange={(e) => setBearerToken(e.target.value)} placeholder="Enter bearer token" /> <button onClick={() => connectUsingBearerToken(bearerToken, { townsConfig })} > {isAgentConnecting ? "Connecting..." : "Connect"} {isAgentConnected && "Connected ✅"} </button> </div> ); } ``` ##
프로젝트로 돌아가기