UNPKG

@lens-protocol/react

Version:

Interacting with the Lens Protocol API using React.

241 lines (240 loc) 8.3 kB
import * as gql from '@lens-protocol/api-bindings'; import { InsufficientGasError, PendingSigningRequestError, TransactionError, UserRejectedError, WalletConnectionError } from '@lens-protocol/domain/entities'; import { OpenActionConfig, ReferencePolicyConfig } from '@lens-protocol/domain/use-cases/publications'; import { BroadcastingError } from '@lens-protocol/domain/use-cases/transactions'; import { PublicationMetadata } from '@lens-protocol/metadata'; import { UseDeferredTask } from "../../helpers/tasks.js"; import { IUploader, UploadError } from "./IUploader.js"; import { PostAsyncResult } from "./useCreatePost.js"; /** * Create new post details. * * @experimental This API is experimental and may change or be removed in future versions. */ export type OptimisticCreatePostArgs = { /** * The metadata object created via `@lens-protocol/metadata` package. */ metadata: PublicationMetadata; /** * The Open Actions associated with the publication. * * @defaultValue empty, no open actions */ actions?: OpenActionConfig[]; /** * The post reference policy. * * Determines the criteria that must be met for a user to be able to comment, quote, or mirror the post. * * @defaultValue `{ type: ReferencePolicyType.ANYONE }` */ reference?: ReferencePolicyConfig; /** * Whether the transaction costs should be sponsored by the Lens API or * should be paid by the authenticated wallet. * * There are scenarios where the sponsorship will be denied regardless of this value. * See {@link BroadcastingError} with: * - {@link BroadcastingErrorReason.NOT_SPONSORED} - the profile is not sponsored * - {@link BroadcastingErrorReason.RATE_LIMITED} - the profile reached the rate limit * - {@link BroadcastingErrorReason.APP_NOT_ALLOWED} - the app is not whitelisted for gasless transactions * * If not specified, or `true`, the hook will attempt a Sponsored Transaction. * Set it to `false` to force it to use a Self-Funded Transaction. */ sponsored?: boolean; }; /** * @experimental This API is experimental and may change or be removed in future versions. */ export type OptimisticCreatePostData = gql.Post | undefined; /** * @experimental This API is experimental and may change or be removed in future versions. */ export type OptimisticCreatePostError = BroadcastingError | PendingSigningRequestError | InsufficientGasError | UserRejectedError | UploadError | WalletConnectionError | TransactionError; /** * `useOptimisticCreatePost` is a React Hook that mirrors the behavior of {@link useCreatePost} but it also * provides an optimistic response. * * **This is still an experimental feature and for now the optimistic behavior is limited to posts * created with Signless Experience.** * * You MUST be authenticated via {@link useLogin} to use this hook. * * @example * ```ts * const { data, execute, loading, error } = useOptimisticCreatePost(uploader); * ``` * * ## Basic usage * * To use the hook, first define an instance of the {@link Uploader} class. * * In this example, we're using a Stateless Uploader. * This type of uploader requires just a function that matches the {@link UploadHandler} signature. * Refer to {@link IUploader} for other types of uploaders. * * ```ts * const uploadHandler = async (file: File) => { * // upload the file and return the public URI * return 'https://example.com/uploaded-file.jpg'; * }; * ``` * * Then, create an instance of the {@link Uploader} class. * * ```ts * const uploader = new Uploader(uploadHandler); * ``` * Then pass the `uploader` to the `useOptimisticCreatePost` hook. * * To create a post, call the `execute` function with the metadata. Contrary to the `useCreatePost` hook you can pass the whole metadata object to the `execute` function. * * ```ts * import { textOnly } from '@lens-protocol/metadata'; * * // ... * * const { data, execute, loading, error } = useOptimisticCreatePost(uploader); * * const post = (content: string) => { * // create the desired metadata via the `@lens-protocol/metadata` package helpers * const metadata = textOnly({ content }); * * // invoke the `execute` function to create the post * const result = await execute({ * metadata, * }); * * // check for failure scenarios * if (result.isFailure()) { * console.log(result.error.message); * } * }; * * return ( * // render data as you would do normally with any Post object * ); * ``` * * The `data` property will be updated with the optimistic Post object immediately after the `execute` call. * * ## Media Upload * * The `useOptimisticCreatePost` hook also supports media uploads. * It accomplishes this by utilizing the provided `uploader` to upload each media file. After the upload, * it updates the supplied metadata with the public URIs of the media files, as returned by the `uploader`. * Finally, it uploads the metadata and creates the post. * * To accomplish this, simply use the local file URL as media URI in the metadata object. * * When using the `@lens-protocol/react-web` package, you can use the `fileToUri` helper to convert a `File` object to a local file URL. * * ```ts fileName="foo" * import { image } from '@lens-protocol/metadata'; * import { fileToUri, useOptimisticCreatePost } from '@lens-protocol/react-web'; * * // ... * * const post = (file: File) => { * // create the desired metadata via the `@lens-protocol/metadata` package helpers * const metadata = image({ * image: { * item: fileToUri(file), * type: MediaImageMimeType.JPEG, * }, * }); * * // invoke the `execute` function to create the post * const result = await execute({ * metadata, * }); * * // check for failure scenarios * if (result.isFailure()) { * console.log(result.error.message); * } * }; * ``` * * When using the `@lens-protocol/react-native` package, you use the property that yield a `file://` URL from the * file picker library of your choice. * * ## Wait for completion * * Optionally, you can wait for the full completion of the post creation. . * * ```ts * const post = (content: string) => { * // create the desired metadata via the `@lens-protocol/metadata` package helpers * const metadata = textOnly({ content }); * * // invoke the `execute` function to create the post * const result = await execute({ * metadata, * }); * * // check for failure scenarios * if (result.isFailure()) { * console.log(result.error.message); * } * * // wait for full completion * const completion = await result.value.waitForCompletion(); * * // check for late failures * if (completion.isFailure()) { * console.log(completion.error.message); * return; * } * * console.log(completion.value); * }; * * return ( * // render data * ); * ``` * * At the end the `data` property will automatically update and the final Post object will be available for further interactions. * * ## Failure scenarios * * In case of upload error an new error type {@link UploadError} will be returned both from the `error` property and from the `Result<T, E>` object from the `execute` function. * * ```ts * const { data, execute, loading, error } = useOptimisticCreatePost(uploader); * * const post = (content: string) => { * // ... * const result = await execute({ * metadata, * }); * * // check for failure scenarios * if (result.isFailure()) { * * // check for upload error * if (result.error instanceof UploadError) { * console.log('There was an error uploading the file', result.error.cause); * return; * } * // other errors handling * * return; * } * }; * * return ( * {error && <p>{error.message}</p>} * // render data * ); * ``` * * @experimental This API is experimental and may change or be removed in future versions without honoring semver. * * @category Publications * @group Hooks */ export declare function useOptimisticCreatePost(uploader: IUploader): UseDeferredTask<OptimisticCreatePostData, OptimisticCreatePostError, OptimisticCreatePostArgs, PostAsyncResult>;