@smartinvoicexyz/hooks
Version:
Unified source for React hooks used across the Smart Invoice protocol.
83 lines (82 loc) • 3.34 kB
JavaScript
import { INVOICE_VERSION, SMART_INVOICE_UPDATABLE_ABI, TOASTS, } from '@smartinvoicexyz/constants';
import { waitForSubgraphSync } from '@smartinvoicexyz/graphql';
import { errorToastHandler, getDateString, uriToDocument, } from '@smartinvoicexyz/utils';
import _ from 'lodash';
import { useCallback, useMemo, useState } from 'react';
import { useChainId, usePublicClient, useSimulateContract, useWriteContract, } from 'wagmi';
import { useDetailsPin } from './useDetailsPin';
export const useLock = ({ invoice, localForm, onTxSuccess, toast, details, }) => {
const currentChainId = useChainId();
const { chainId: invoiceChainId, metadata } = _.pick(invoice, [
'chainId',
'metadata',
]);
const { description, document } = localForm.getValues();
const publicClient = usePublicClient();
const detailsData = useMemo(() => {
if (details) {
return null;
}
const now = Math.floor(new Date().getTime() / 1000);
const title = `Dispute ${metadata?.title} at ${getDateString(now)}`;
return {
version: INVOICE_VERSION,
id: _.join([title, now, INVOICE_VERSION], '-'),
title,
description,
documents: document ? [uriToDocument(document)] : [],
createdAt: now,
};
}, [description, document, metadata, details]);
const { data: detailsHash, isLoading: detailsLoading } = useDetailsPin(detailsData, true);
const { data, isLoading: prepareLoading, error: prepareError, } = useSimulateContract({
address: invoice?.address,
functionName: 'lock',
abi: SMART_INVOICE_UPDATABLE_ABI,
args: [details ?? detailsHash],
query: {
enabled: !!invoice?.address &&
!!description &&
(!!details || !!detailsHash) &&
currentChainId === invoiceChainId,
},
});
const [waitingForTx, setWaitingForTx] = useState(false);
const { writeContractAsync, isPending: writeLoading, error: writeError, } = useWriteContract({
mutation: {
onSuccess: async (hash) => {
setWaitingForTx(true);
toast.loading(TOASTS.useLock.waitingForTx);
const receipt = await publicClient?.waitForTransactionReceipt({ hash });
toast.loading(TOASTS.useLock.waitingForIndex);
if (receipt && publicClient) {
await waitForSubgraphSync(publicClient.chain.id, receipt.blockNumber);
}
setWaitingForTx(false);
onTxSuccess?.();
},
onError: error => errorToastHandler('useLock', error, toast),
},
});
const writeAsync = useCallback(async () => {
try {
if (!data) {
throw new Error('simulation data is not available');
}
return writeContractAsync(data.request);
}
catch (error) {
errorToastHandler('useLock', error, toast);
return undefined;
}
}, [writeContractAsync, data]);
return {
writeAsync,
isLoading: prepareLoading ||
writeLoading ||
waitingForTx ||
!(details || !detailsLoading),
prepareError,
writeError,
};
};