Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main into dev #68

Merged
merged 4 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simple-staking",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
22 changes: 15 additions & 7 deletions src/app/components/Delegations/Delegation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import { AiOutlineInfoCircle } from "react-icons/ai";
import { FaBitcoin } from "react-icons/fa";
import { IoIosWarning } from "react-icons/io";
import { Tooltip } from "react-tooltip";

Expand Down Expand Up @@ -121,12 +122,17 @@ export const Delegation: React.FC<DelegationProps> = ({
<p>overflow</p>
</div>
)}
<div className="grid grid-flow-col grid-cols-2 grid-rows-2 items-center gap-2 lg:grid-flow-row lg:grid-cols-5 lg:grid-rows-1">
<p>
{maxDecimals(satoshiToBtc(stakingValueSat), 8)} {coinName}
<div className="grid grid-flow-col grid-cols-2 grid-rows-3 items-center gap-2 lg:grid-flow-row lg:grid-cols-5 lg:grid-rows-1">
<div className="flex gap-1 items-center order-1">
<FaBitcoin className="text-primary" />
<p>
{maxDecimals(satoshiToBtc(stakingValueSat), 8)} {coinName}
</p>
</div>
<p className="order-3 lg:order-2">
{durationTillNow(startTimestamp, currentTime)}
</p>
<p>{durationTillNow(startTimestamp, currentTime)}</p>
<div className="hidden justify-center lg:flex">
<div className="justify-center lg:flex order-2 lg:order-3">
<a
href={`${mempoolApiUrl}/tx/${stakingTxHash}`}
target="_blank"
Expand All @@ -136,11 +142,13 @@ export const Delegation: React.FC<DelegationProps> = ({
{trim(stakingTxHash)}
</a>
</div>
{/* Future data placeholder */}
<div className="order-5 lg:hidden" />
{/*
we need to center the text without the tooltip
add its size 12px and gap 4px, 16/2 = 8px
*/}
<div className="relative flex justify-end lg:left-[8px] lg:justify-center">
<div className="relative flex justify-end lg:left-[8px] lg:justify-center order-4">
<div className="flex items-center gap-1">
<p>{renderState()}</p>
<span
Expand All @@ -154,7 +162,7 @@ export const Delegation: React.FC<DelegationProps> = ({
<Tooltip id={`tooltip-${stakingTxHash}`} className="tooltip-wrap" />
</div>
</div>
{generateActionButton()}
<div className="order-6">{generateActionButton()}</div>
</div>
</div>
);
Expand Down
18 changes: 11 additions & 7 deletions src/app/components/Modals/ErrorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface ErrorModalProps {
errorMessage: string;
errorState?: ErrorState;
errorTime: Date;
noCancel?: boolean;
}

export const ErrorModal: React.FC<ErrorModalProps> = ({
Expand All @@ -20,7 +21,8 @@ export const ErrorModal: React.FC<ErrorModalProps> = ({
onRetry,
errorMessage,
errorState,
errorTime,
noCancel,
// errorTime, // This prop is not used in the component
}) => {
const { error, retryErrorAction } = useError();

Expand Down Expand Up @@ -93,12 +95,14 @@ export const ErrorModal: React.FC<ErrorModalProps> = ({
<p className="text-center">{getErrorMessage()}</p>
</div>
<div className="mt-4 flex justify-around gap-4">
<button
className="btn btn-outline flex-1 rounded-lg px-2"
onClick={() => onClose()}
>
Cancel
</button>
{!noCancel && ( // Only show the cancel button if noCancel is false or undefined
<button
className="btn btn-outline flex-1 rounded-lg px-2"
onClick={() => onClose()}
>
Cancel
</button>
)}
{onRetry && (
<button
className="btn-primary btn flex-1 rounded-lg px-2 text-white"
Expand Down
24 changes: 11 additions & 13 deletions src/app/components/Staking/Form/StakingFee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,20 @@ export const StakingFee: React.FC<StakingFeeProps> = ({
<div className="flex flex-col justify-center gap-1 items-center">
<div className="min-h-8 flex justify-center flex-col items-center">
{mempoolFeeRates ? (
<p>
Recommended fee rate: <strong>{defaultFeeRate} sats/vB</strong>
</p>
<div>
<p>
Recommended fee rate: <strong>{defaultFeeRate} sats/vB</strong>
</p>
<p>
Transaction fee amount:{" "}
<strong>
{satoshiToBtc(stakingFeeSat)} {coinName}
</strong>
</p>
</div>
) : (
<LoadingSmall text="Loading recommended fee rate..." />
)}
{stakingFeeSat ? (
<p>
Transaction fee amount:{" "}
<strong>
{satoshiToBtc(stakingFeeSat)} {coinName}
</strong>
</p>
) : (
<LoadingSmall text="Loading transaction fee amount..." />
)}
</div>
<button
className="btn btn-sm btn-link no-underline"
Expand Down
12 changes: 11 additions & 1 deletion src/app/components/Staking/Staking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,16 @@ export const Staking: React.FC<StakingProps> = ({
errorState: ErrorState.STAKING,
errorTime: new Date(),
},
retryAction: handleSign,
noCancel: true,
retryAction: () => {
// in case of error, we need to partly reset the state
setStakingAmountSat(0);
setSelectedFeeRate(0);
setPreviewModalOpen(false);
setResetFormInputs(!resetFormInputs);
// and refetch the UTXOs
queryClient.invalidateQueries({ queryKey: [UTXO_KEY, address] });
},
});
}
};
Expand Down Expand Up @@ -578,6 +587,7 @@ export const Staking: React.FC<StakingProps> = ({
stakingAmountSat,
stakingTimeBlocksWithFixed,
!!finalityProvider,
stakingFeeSat,
);

const previewReady =
Expand Down
18 changes: 13 additions & 5 deletions src/app/context/Error/ErrorContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface ErrorContextType {
retryErrorAction?: () => void;
showError: (showErrorParams: ShowErrorParams) => void;
hideError: () => void;
noCancel?: boolean;
handleError: ({
error,
hasError,
Expand All @@ -34,6 +35,7 @@ interface ErrorContextType {

export const ErrorProvider: React.FC<ErrorProviderProps> = ({ children }) => {
const [isErrorOpen, setIsErrorOpen] = useState(false);
const [isNoCancel, setIsNoCancel] = useState(false);
const [error, setError] = useState<ErrorType>({
message: "",
errorTime: new Date(),
Expand All @@ -43,11 +45,15 @@ export const ErrorProvider: React.FC<ErrorProviderProps> = ({ children }) => {
(() => void) | undefined
>();

const showError = useCallback(({ error, retryAction }: ShowErrorParams) => {
setError(error);
setIsErrorOpen(true);
setRetryErrorAction(() => retryAction);
}, []);
const showError = useCallback(
({ error, retryAction, noCancel }: ShowErrorParams) => {
setError(error);
setIsErrorOpen(true);
setIsNoCancel(noCancel ?? false);
setRetryErrorAction(() => retryAction);
},
[],
);

const hideError = useCallback(() => {
setIsErrorOpen(false);
Expand All @@ -58,6 +64,7 @@ export const ErrorProvider: React.FC<ErrorProviderProps> = ({ children }) => {
errorState: undefined,
});
setRetryErrorAction(undefined);
setIsNoCancel(false);
}, 300);
}, []);

Expand All @@ -83,6 +90,7 @@ export const ErrorProvider: React.FC<ErrorProviderProps> = ({ children }) => {
showError,
hideError,
retryErrorAction,
noCancel: isNoCancel,
handleError,
};

Expand Down
2 changes: 2 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const Home: React.FC<HomeProps> = () => {
showError,
hideError,
retryErrorAction,
noCancel,
handleError,
} = useError();
const { isTermsOpen, closeTerms } = useTerms();
Expand Down Expand Up @@ -397,6 +398,7 @@ const Home: React.FC<HomeProps> = () => {
errorTime={error.errorTime}
onClose={hideError}
onRetry={retryErrorAction}
noCancel={noCancel}
/>
<TermsModal open={isTermsOpen} onClose={closeTerms} />
</main>
Expand Down
1 change: 1 addition & 0 deletions src/app/types/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export interface ErrorHandlerParam {
export interface ShowErrorParams {
error: ErrorType;
retryAction?: () => void;
noCancel?: boolean;
}
8 changes: 8 additions & 0 deletions src/utils/isStakingSignReady.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const isStakingSignReady = (
amount: number,
time: number,
fpSelected: boolean,
stakingFeeSat: number,
): { isReady: boolean; reason: string } => {
if (!fpSelected)
return {
Expand Down Expand Up @@ -39,6 +40,13 @@ export const isStakingSignReady = (
isReady: false,
reason: "Please enter a valid staking period",
};
} else if (stakingFeeSat === 0) {
// This is a temporary solution when the fee is not calculated or throw an error
// the staking fee is set to 0 by stakingFeeSat from staking.tsx
return {
isReady: false,
reason: "Not enough funds to cover fees for staking",
};
}
return {
isReady: true,
Expand Down
12 changes: 10 additions & 2 deletions tests/utils/isStakingSignReady.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isStakingSignReady } from "@/utils/isStakingSignReady";

describe("utils/isStakingSignReady", () => {
it("should return false with reason if fpSelected is false", () => {
const result = isStakingSignReady(1, 2, 3, 4, 5, 6, false);
const result = isStakingSignReady(1, 2, 3, 4, 5, 6, false, 1);
expect(result.isReady).toBe(false);
expect(result.reason).toBe("Please select a finality provider");
});
Expand Down Expand Up @@ -44,6 +44,7 @@ describe("utils/isStakingSignReady", () => {
input.amount,
6,
true,
1,
);
expect(result.isReady).toBe(false);
expect(result.reason).toBe("Please enter a valid stake amount");
Expand Down Expand Up @@ -87,14 +88,21 @@ describe("utils/isStakingSignReady", () => {
5,
input.time,
true,
1,
);
expect(result.isReady).toBe(false);
expect(result.reason).toBe("Please enter a valid staking period");
});
});

it("should return false with reason if sufficientBalance is false", () => {
const result = isStakingSignReady(1, 10, 20, 30, 5, 25, true, 0);
expect(result.isReady).toBe(false);
expect(result.reason).toBe("Not enough funds to cover fees for staking");
});

it("should return true with empty reason if amount and time are ready", () => {
const result = isStakingSignReady(1, 10, 20, 30, 5, 25, true);
const result = isStakingSignReady(1, 10, 20, 30, 5, 25, true, 1);
expect(result.isReady).toBe(true);
expect(result.reason).toBe("");
});
Expand Down