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

Fix ZapPlanner Subscription Budget Calculation and Interval Enforcement (Fixes #60) #61

Closed
wants to merge 3 commits into from
Closed
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
45 changes: 35 additions & 10 deletions app/confirm/components/ConfirmSubscriptionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"use client";

import { useForm } from "react-hook-form";
import { CreateSubscriptionRequest } from "types/CreateSubscriptionRequest";
import { useRouter } from "next/navigation";
import { CreateSubscriptionResponse } from "types/CreateSubscriptionResponse";
import React from "react";
import React, { useEffect, useState } from "react";
import { webln } from "@getalby/sdk";
import { UnconfirmedSubscription } from "types/UnconfirmedSubscription";
import { isValidNostrConnectUrl } from "lib/validation";
Expand Down Expand Up @@ -42,7 +40,7 @@ export function ConfirmSubscriptionForm({
},
});

const [isNavigating, setNavigating] = React.useState(false);
const [isNavigating, setNavigating] = useState(false);
const { push } = useRouter();
const hasLinkedWallet = !!watch("nostrWalletConnectUrl");

Expand All @@ -64,7 +62,7 @@ export function ConfirmSubscriptionForm({
if (isValidNostrConnectUrl(url)) {
setValue("nostrWalletConnectUrl", url);
} else {
throw new Error("Received invalid NWC URL");
throw an Error("Received invalid NWC URL");
}
} catch (error) {
if (error) {
Expand All @@ -73,19 +71,47 @@ export function ConfirmSubscriptionForm({
}
};

const getMillisecondsForInterval = (interval: string) => {
switch (interval) {
case "daily":
return 24 * 60 * 60 * 1000; // 1 day in milliseconds
case "weekly":
return 7 * 24 * 60 * 60 * 1000; // 1 week in milliseconds
case "monthly":
// Note: This is a simplified calculation; adjust as needed
return 30 * 24 * 60 * 60 * 1000; // 30 days in milliseconds
default:
return 24 * 60 * 60 * 1000; // Default to daily (1 day in milliseconds)
}
};

const onSubmit = handleSubmit(async (data) => {
if (!data.nostrWalletConnectUrl) {
toast.error("Please link your wallet");
return;
}

const selectedInterval = data.sleepDuration;
const intervalMilliseconds = getMillisecondsForInterval(selectedInterval);

const oneYearInMilliseconds = 31536000000; // One year in milliseconds
if (selectedInterval === "yearly" && intervalMilliseconds > oneYearInMilliseconds) {
toast.error("Interval cannot be more than 1 year");
return;
}

const satoshis = getSatoshisForInterval(intervalMilliseconds);

data.max_amount = satoshis;

const subscriptionId = await createSubscription(data);
if (subscriptionId) {
toast.success("Recurring payment created");
setNavigating(true);
push(
`/subscriptions/${subscriptionId}${
returnUrl ? `?returnUrl=${returnUrl}` : ""
}`,
}`
);
}
});
Expand Down Expand Up @@ -141,7 +167,7 @@ export function ConfirmSubscriptionForm({
</h2>
</div>
<p className="font-body">
Nostr Wallet Connect allows you to securely authorise
Nostr Wallet Connect allows you to securely authorize
ZapPlanner to perform transactions from your lightning
wallet on your behalf.
</p>
Expand Down Expand Up @@ -255,7 +281,7 @@ export function ConfirmSubscriptionForm({
}

async function createSubscription(
createSubscriptionRequest: CreateSubscriptionRequest,
createSubscriptionRequest: CreateSubscriptionRequest
): Promise<string | undefined> {
const res = await fetch("/api/subscriptions", {
method: "POST",
Expand All @@ -267,7 +293,6 @@ async function createSubscription(
toast.error(res.status + " " + res.statusText);
return undefined;
}
const createSubscriptionResponse =
(await res.json()) as CreateSubscriptionResponse;
const createSubscriptionResponse = (await res.json()) as CreateSubscriptionResponse;
return createSubscriptionResponse.subscriptionId;
}