UNPKG

@lens-protocol/react

Version:

Interacting with the Lens Protocol API using React.

236 lines (235 loc) 8.06 kB
import { InsufficientGasError, PendingSigningRequestError, UserRejectedError, WalletConnectionError } from '@lens-protocol/domain/entities'; import { BroadcastingError } from '@lens-protocol/domain/use-cases/transactions'; import { InsufficientAllowanceError, InsufficientFundsError } from '@lens-protocol/domain/use-cases/wallets'; import { UseDeferredTask } from "../../helpers/tasks.js"; import { AsyncTransactionResult } from "../adapters/AsyncTransactionResult.js"; import { OpenActionArgs, UseOpenActionArgs } from "./types.js"; /** * An object representing the result of an open action is finalized. * * It allows to wait for the action to be fully processed and indexed. */ export type OpenActionAsyncResult = AsyncTransactionResult<void>; /** * `useOpenAction` is a React Hook that allows to perform an Open Action on a publication. * * You MUST be authenticated via {@link useLogin} to use this hook. * * @example * ```ts * const { execute, error, loading } = useOpenAction({ * action: { * kind: OpenActionKind.COLLECT, * } * }); * ``` * * ## Collect a publication * * You can use the `useOpenAction` hook to collect a publication. * * ```ts * const { execute, error, loading } = useOpenAction({ * action: { * kind: OpenActionKind.COLLECT, * } * }); * * const collect = async (publication: AnyPublication) => { * const result = await execute({ publication }); * } * ``` * * It supports seamlessly new collect Open Action modules as well as legacy collect modules. * * ## Failure scenarios * * You can handle possible failure scenarios by checking the `result` value. * * ```ts * const collect = async (publication: AnyPublication) => { * const result = await execute({ publication }); * * if (result.isFailure()) { * switch (result.error.name) { * case 'BroadcastingError': * console.log('There was an error broadcasting the transaction', error.message); * break; * * case 'PendingSigningRequestError': * console.log( * 'There is a pending signing request in your wallet. ' + * 'Approve it or discard it and try again.' * ); * break; * * case 'InsufficientAllowanceError': * const requestedAmount = result.error.requestedAmount; * console.log( * 'You must approve the contract to spend at least: '+ * `${requestedAmount.asset.symbol} ${requestedAmount.toSignificantDigits(6)}` * ); * break; * * case 'InsufficientFundsError': * const requestedAmount = result.error.requestedAmount; * console.log( * 'You do not have enough funds to pay for this collect fee: '+ * `${requestedAmount.asset.symbol} ${requestedAmount.toSignificantDigits(6)}` * ); * break; * * case 'WalletConnectionError': * console.log('There was an error connecting to your wallet', error.message); * break; * * case 'UserRejectedError': * // the user decided to not sign, usually this is silently ignored by UIs * break; * } * return; * } * }; * ``` * * ## Wait for completion * * You can always wait the operation to be fully processed and indexed by Lens API. * * ```ts * const collect = async (publication: AnyPublication) => { * const result = await execute({ publication }); * * if (result.isFailure()) { * // handle failure scenarios * return; * } * * // this might take a while depending on the congestion of the network * const completion = await result.value.waitForCompletion(); * * if (completion.isFailure()) { * console.log('There was an processing the transaction', completion.error.message); * return; * } * * console.log('Open action executed successfully'); * }; * ``` * * ## Collect referrers * * When collecting a publication using the new SimpleCollectOpenAction or MultirecipientFeeCollectOpenAction * you can specify a list of referrer Publication and/or Profile IDs. * * ```ts * const { execute, error, loading } = useOpenAction({ * action: { * kind: OpenActionKind.COLLECT, * referrers: [ * publicationId, * profileId, * ], * }, * }); * ``` * * The referrers will split the referral reward of any collect fee paid by the collector. * * ## Public collect * * You can use the `useOpenAction` hook to collect a publication with just a wallet. * First make sure you logged-in via {@link useLogin} with just an EVM address. * * Then you can use the `useOpenAction` to collect a publication as mentioned above. * * ## Custom open action * * You can use the `useOpenAction` hook to execute a custom Open Action. * * You must know the address of the Open Action module and the data required to execute it. * * ```ts * const { execute, error, loading } = useOpenAction({ * action: { * kind: OpenActionKind.UNKNOWN, * address: '0x...', // the address of the Open Action module * data: '0x...', // any data needed to execute the Open Action * } * }); * * const collect = async (publication: AnyPublication) => { * const result = await execute({ publication }); * * // ... * } * ``` * * ## Self-funded approach * * It just takes a single parameter to disable the sponsorship of the transaction gas costs. * * ```ts * const collect = async (publication: AnyPublication) => { * const result = await execute({ * publication, * sponsored: false, * }); * * if (result.isFailure()) { * switch (result.error.name) { * case 'InsufficientGasError': * console.log('You do not have enough funds to pay for the transaction gas cost.'); * break; * * // ... * } * return; * } * * // ... * } * ``` * In this example you can also see a new error type: {@link InsufficientGasError}. This * error happens only with self-funded transactions and it means that the wallet does not * have enough funds to pay for the transaction gas costs. * * ## Self-funded fallback * * If for some reason the Lens API cannot sponsor the transaction, the hook will fail with a {@link BroadcastingError} with one of the following reasons: * - {@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 * * In those cases you can retry the transaction as self-funded like in the following example: * * ```ts * const collect = async (publication: AnyPublication) => { * const sponsoredResult = await execute({ publication }); * * if (sponsoredResult.isFailure()) { * switch (sponsoredResult.error.name) { * case 'BroadcastingError': * if ([BroadcastingErrorReason.NOT_SPONSORED, BroadcastingErrorReason.RATE_LIMITED].includes(sponsoredResult.error.reason)) { * * const selfFundedResult = await execute({ publication, sponsored: false }); * * // continue with selfFundedResult as in the previous example * } * break; * * // ... * } * } * ``` * * In this example we omitted {@link BroadcastingErrorReason.APP_NOT_ALLOWED} as it's not normally a problem per-se. * It just requires the app to apply for whitelisting. See https://docs.lens.xyz/docs/gasless-and-signless#whitelisting-your-app. * * You can still include it in your fallback logic if you want to. For example to unblock testing your app from a domain that is not the * whitelisted one (e.g. localhost). * * @category Publications * @group Hooks */ export declare function useOpenAction(args: UseOpenActionArgs): UseDeferredTask<OpenActionAsyncResult, BroadcastingError | InsufficientAllowanceError | InsufficientFundsError | InsufficientGasError | PendingSigningRequestError | UserRejectedError | WalletConnectionError, OpenActionArgs>;