Skip to content

Commit

Permalink
add onStatus prop and lifeCycleStatus to Pay
Browse files Browse the repository at this point in the history
  • Loading branch information
0xAlec committed Sep 9, 2024
1 parent 376a79e commit 64faa4f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
10 changes: 9 additions & 1 deletion src/pay/components/Pay.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { LifeCycleStatus } from '../../transaction';
import { useIsMounted } from '../../useIsMounted';
import { PayProvider } from './PayProvider';

Expand All @@ -6,11 +7,13 @@ export function Pay({
chargeId,
children,
className,
onStatus,
}: {
chainId: number;
chargeId: string;
children: React.ReactNode;
className?: string;
onStatus?: (status: LifeCycleStatus) => void;
}) {
const isMounted = useIsMounted();
// prevents SSR hydration issue
Expand All @@ -19,7 +22,12 @@ export function Pay({
}

return (
<PayProvider chargeId={chargeId} chainId={chainId} className={className}>
<PayProvider
chargeId={chargeId}
chainId={chainId}
className={className}
onStatus={onStatus}
>
{children}
</PayProvider>
);
Expand Down
4 changes: 2 additions & 2 deletions src/pay/components/PayButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { cn, text as styleText } from '../../styles/theme';
import { usePayContext } from './PayProvider';

export function PayButton({ text = 'Pay with Crypto' }: { text?: string }) {
const { lifecycleStatus, handleSubmit } = usePayContext();
const { lifeCycleStatus, handleSubmit } = usePayContext();

const isLoading = lifecycleStatus?.statusName === 'transactionPending';
const isLoading = lifeCycleStatus?.statusName === 'transactionPending';

return (
<button
Expand Down
73 changes: 58 additions & 15 deletions src/pay/components/PayProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@ import {
createContext,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';
import type { ContractFunctionParameters } from 'viem';
import { useAccount, useConnect } from 'wagmi';
import { useWaitForTransactionReceipt } from 'wagmi';
import { useValue } from '../../internal/hooks/useValue';
import type { LifeCycleStatus } from '../../transaction';
import { useCallsStatus } from '../../transaction/hooks/useCallsStatus';
import { useWriteContracts } from '../../transaction/hooks/useWriteContracts';
import { useCommerceContracts } from '../hooks/useCommerceContracts';

type PayContextType = {
handleSubmit: () => void;
lifecycleStatus?: LifeCycleStatus;
lifeCycleStatus?: LifeCycleStatus;
setLifeCycleStatus: (status: LifeCycleStatus) => void;
};

Expand All @@ -36,15 +39,17 @@ export function PayProvider({
chargeId,
children,
className,
onSuccess,
onStatus,
}: {
chainId: number;
chargeId: string;
children: React.ReactNode;
className?: string;
onSuccess?: (transactionId: string) => void;
onStatus?: (status: LifeCycleStatus) => void;
}) {
const contractsRef = useRef<ContractFunctionParameters[] | undefined>(
undefined,
);
// Core hooks
const { address, isConnected } = useAccount();
const { connectAsync, connectors } = useConnect({
mutation: {
Expand All @@ -53,30 +58,68 @@ export function PayProvider({
},
},
});
const contractsRef = useRef<ContractFunctionParameters[] | undefined>(
undefined,
);
const [transactionId, setTransactionId] = useState('');
const [lifecycleStatus, setLifeCycleStatus] = useState<LifeCycleStatus>({
// Component lifecycle
const [lifeCycleStatus, setLifeCycleStatus] = useState<LifeCycleStatus>({
statusName: 'init',
statusData: null,
});

// TODO: use the transaction hook
const { writeContractsAsync } = useWriteContracts({
setLifeCycleStatus,
setTransactionId,
});

// Transaction hooks
const fetchContracts = useCommerceContracts({
address,
chainId,
chargeId,
contractsRef,
});
const { status, writeContractsAsync } = useWriteContracts({
setLifeCycleStatus,
setTransactionId,
});
const { transactionHash, status: callStatus } = useCallsStatus({
setLifeCycleStatus,
transactionId,
});
const { data: receipt } = useWaitForTransactionReceipt({
hash: transactionHash,
});

const handleSubmit = useCallback(async () => {
// Component lifecycle emitters
useEffect(() => {
// Emit Status
onStatus?.(lifeCycleStatus);
}, [
lifeCycleStatus,
lifeCycleStatus.statusData, // Keep statusData, so that the effect runs when it changes
lifeCycleStatus.statusName, // Keep statusName, so that the effect runs when it changes
]);

// Set transaction pending status when writeContracts is pending
useEffect(() => {
if (status === 'pending') {
setLifeCycleStatus({
statusName: 'transactionPending',
statusData: null,
});
}
}, [status]);
// Trigger success status when receipt is generated by useWaitForTransactionReceipt
useEffect(() => {
if (!receipt) {
return;
}
setLifeCycleStatus({
statusName: 'transactionPending',
statusData: null,
statusName: 'success',
statusData: {
transactionReceipts: [receipt],
},
});
}, [receipt]);

const handleSubmit = useCallback(async () => {
if (isConnected) {
// Fetch contracts
await fetchContracts();
Expand All @@ -102,7 +145,7 @@ export function PayProvider({

const value = useValue({
handleSubmit,
lifecycleStatus,
lifeCycleStatus,
setLifeCycleStatus,
});
return <PayContext.Provider value={value}>{children}</PayContext.Provider>;
Expand Down

0 comments on commit 64faa4f

Please sign in to comment.