Skip to content
Open
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
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
NEXT_PUBLIC_SOLANA_URL=
NEXT_PUBLIC_SOLANA_URL=
NEXT_PUBLIC_HELIUM_TRANSACTION_API=https://blockchain-api.web.helium.io
6 changes: 6 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ const nextConfig = {
port: "",
pathname: "/**/**",
},
{
protocol: "https",
hostname: "entities.nft.helium.io",
port: "",
pathname: "/**/**",
},
...(process.env.NODE_ENV === "development" ? [
{
protocol: "http",
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@coral-xyz/anchor": "^0.31.0",
"@helium/account-fetch-cache": "^0.11.5",
"@helium/account-fetch-cache-hooks": "^0.11.5",
"@helium/blockchain-api": "^0.11.17",
"@helium/helium-react-hooks": "^0.11.5",
"@helium/hpl-crons-sdk": "^0.11.5",
"@helium/modular-governance-hooks": "^0.1.5",
Expand All @@ -25,6 +26,8 @@
"@helium/voter-stake-registry-sdk": "^0.11.5",
"@jup-ag/jup-mobile-adapter": "^0.0.2",
"@metaplex-foundation/mpl-token-metadata": "2.10.0",
"@orpc/client": "^1.13.4",
"@orpc/contract": "^1.13.4",
"@project-serum/anchor": "^0.26.0",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
Expand Down
47 changes: 21 additions & 26 deletions src/app/[network]/positions/delegate-all/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { ContentSection } from "@/components/ContentSection";
import { Header } from "@/components/Header";
import { DelegateAllPositionsPrompt } from "@/components/PositionManager/DelegateAllPositionsPrompt";
import { IOT_SUB_DAO_KEY, MOBILE_SUB_DAO_KEY } from "@/lib/constants";
import { onInstructions } from "@/lib/utils";
import { IOT_MINT, MOBILE_MINT } from "@helium/spl-utils";
import { useGovernance } from "@/providers/GovernanceProvider";
import { useDelegatePositionMutation } from "@/hooks/useGovernanceMutations";
import {
useAnchorProvider,
useSolanaUnixNow,
} from "@helium/helium-react-hooks";
import {
SubDaoWithMeta,
useDelegatePositions,
} from "@helium/voter-stake-registry-hooks";
import { WalletSignTransactionError } from "@solana/wallet-adapter-base";
import BN from "bn.js";
Expand All @@ -26,7 +25,8 @@ export default function DelegateAllPositionsPage() {
const { positions, subDaos } = useGovernance();
const [subDao, setSubDao] = useState<SubDaoWithMeta | null>(null);
const [automationEnabled, setAutomationEnabled] = useState(true);
const provider = useAnchorProvider();

const delegateMutation = useDelegatePositionMutation();

const now = useSolanaUnixNow();
const delegatedPositions = useMemo(
Expand All @@ -43,19 +43,6 @@ export default function DelegateAllPositionsPage() {
[positions, now]
);

const {
delegatePositions,
rentFee: solFees = 0,
prepaidTxFees = 0,
insufficientBalance = false,
error,
loading,
} = useDelegatePositions({
automationEnabled,
positions: unexpiredPositions,
subDao: subDao || undefined,
});

useEffect(() => {
if (!subDaos || !delegatedPositions || subDao) return;
const mobileSubDao = subDaos.find((sd) =>
Expand Down Expand Up @@ -102,9 +89,17 @@ export default function DelegateAllPositionsPage() {

const handleConfirm = async () => {
try {
await delegatePositions({
onInstructions: onInstructions(provider),
});
await delegateMutation.submit(
{
positionMints: unexpiredPositions.map((p) => p.mint.toBase58()),
subDaoMint: subDao?.pubkey.equals(IOT_SUB_DAO_KEY) ? IOT_MINT.toBase58() : MOBILE_MINT.toBase58(),
automationEnabled,
},
{
header: "Delegate All Positions",
message: "Delegating all positions to subnetwork",
}
);
toast("Delegations updated");
router.replace(`/${network}/positions`);
} catch (e: any) {
Expand All @@ -121,18 +116,18 @@ export default function DelegateAllPositionsPage() {
<ContentSection>
<DelegateAllPositionsPrompt
positions={unexpiredPositions}
isSubmitting={loading}
isSubmitting={delegateMutation.isPending}
onCancel={() => router.back()}
onConfirm={handleConfirm}
automationEnabled={automationEnabled}
setAutomationEnabled={setAutomationEnabled}
subDao={subDao}
setSubDao={setSubDao}
solFees={solFees}
prepaidTxFees={prepaidTxFees}
error={error ? String(error) : undefined}
loading={loading}
insufficientBalance={!!insufficientBalance}
solFees={delegateMutation.estimatedSolFee?.uiAmount ?? 0}
prepaidTxFees={0}
error={delegateMutation.error ? String(delegateMutation.error) : undefined}
loading={delegateMutation.isPending}
insufficientBalance={false}
/>
</ContentSection>
</>
Expand Down
71 changes: 33 additions & 38 deletions src/components/CreatePositionModal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
"use client";

import { daysToSecs, onInstructions } from "@/lib/utils";
import { daysToSecs } from "@/lib/utils";
import { useGovernance } from "@/providers/GovernanceProvider";
import {
useAnchorProvider,
useMint,
useOwnedAmount,
} from "@helium/helium-react-hooks";
import { HNT_MINT, toBN, toNumber } from "@helium/spl-utils";
import {
PositionWithMeta,
calcLockupMultiplier,
useCreatePosition,
} from "@helium/voter-stake-registry-hooks";
import { useCreatePositionMutation } from "@/hooks/useGovernanceMutations";
import { WalletSignTransactionError } from "@solana/wallet-adapter-base";
import { useWallet } from "@/hooks/useWallet";
import { PublicKey } from "@solana/web3.js";
Expand All @@ -30,26 +29,23 @@ import { SubDaoSelection } from "./SubDaoSelection";
import { Button } from "./ui/button";
import { Dialog, DialogContent, DialogTrigger } from "./ui/dialog";
import { PositionPreview } from "./PositionPreview";
import { MOBILE_SUB_DAO_KEY } from "@/lib/constants";
import { IOT_SUB_DAO_KEY, MOBILE_SUB_DAO_KEY } from "@/lib/constants";
import { IOT_MINT, MOBILE_MINT } from "@helium/spl-utils";
import { DataSplitBars } from "./DataSplitBars";
import { AutomationSettings } from "./AutomationSettings";

export const CreatePositionModal: FC<React.PropsWithChildren<{}>> = ({
children,
}) => {
const provider = useAnchorProvider();
const [step, setStep] = useState(1);
const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [formValues, setFormValues] = useState<LockTokensFormValues>();
const [selectedSubDaoPk, setSelectedSubDaoPk] = useState<PublicKey>();
const [automationEnabled, setAutomationEnabled] = useState(true);
const { publicKey: wallet } = useWallet();
const { mint, subDaos, registrar, refetch: refetchState } = useGovernance();
const { amount: ownedAmount, decimals } = useOwnedAmount(wallet, mint);
const { error: createPositionError, createPosition, rentFee, prepaidTxFees, insufficientBalance } = useCreatePosition({
automationEnabled,
});
const createPositionMutation = useCreatePositionMutation();
const steps = useMemo(() => (mint.equals(HNT_MINT) ? 3 : 2), [mint]);

useEffect(() => {
Expand Down Expand Up @@ -107,7 +103,7 @@ export const CreatePositionModal: FC<React.PropsWithChildren<{}>> = ({
);

const handleOpenChange = () => {
setIsSubmitting(false);
createPositionMutation.reset();
setFormValues(undefined);
setOpen(!open);
setStep(1);
Expand All @@ -121,43 +117,43 @@ export const CreatePositionModal: FC<React.PropsWithChildren<{}>> = ({
const handleLockTokens = async () => {
try {
const { amount, lockupPeriodInDays, lockupKind } = formValues!;
setIsSubmitting(true);

if (decimals) {
const amountToLock = toBN(amount, decimals);
await createPosition({
amount: amountToLock,
lockupPeriodsInDays: lockupPeriodInDays,
lockupKind: lockupKind,
mint,
...(subDaos && selectedSubDaoPk
? {
subDao: subDaos.find((subDao) =>
subDao.pubkey.equals(selectedSubDaoPk!)
)!,
}
: {}),
onInstructions: onInstructions(provider),
});
await createPositionMutation.submit(
{
amount: amountToLock.toString(),
mint: mint.toBase58(),
lockupKind: lockupKind as "cliff" | "constant",
lockupPeriodsInDays: lockupPeriodInDays,
...(subDaos && selectedSubDaoPk
? {
subDaoMint: selectedSubDaoPk.equals(IOT_SUB_DAO_KEY)
? IOT_MINT.toBase58()
: MOBILE_MINT.toBase58(),
automationEnabled,
}
: {}),
},
{
header: "Create Position",
message: "Locking tokens and creating position",
}
);

toast.success("Position created successfully");
setIsSubmitting(false);

if (!createPositionError) {
setOpen(false);
refetchState();
} else {
toast(createPositionError.message);
}
setOpen(false);
refetchState();
}
} catch (e: any) {
setIsSubmitting(false);
if (!(e instanceof WalletSignTransactionError)) {
toast(e.message || "Position creation failed, please try again");
}
}
};

const isSubmitting = createPositionMutation.isPending;

const verb =
(step === 1 && "Create") ||
(steps > 2 && step === 2 && "Delegate") ||
Expand Down Expand Up @@ -215,8 +211,8 @@ export const CreatePositionModal: FC<React.PropsWithChildren<{}>> = ({
<AutomationSettings
automationEnabled={automationEnabled}
setAutomationEnabled={setAutomationEnabled}
solFees={rentFee}
prepaidTxFees={prepaidTxFees}
solFees={createPositionMutation.estimatedSolFee?.uiAmount ?? 0}
prepaidTxFees={0}
/>

<div className="flex flex-col gap-4 p-4 text-sm bg-slate-600 rounded">
Expand Down Expand Up @@ -250,9 +246,8 @@ export const CreatePositionModal: FC<React.PropsWithChildren<{}>> = ({
<Button
className="flex-grow text-foreground gap-2"
onClick={() => setStep(step + 1)}
disabled={!!insufficientBalance}
>
{insufficientBalance ? "Insufficient SOL" : "Review"}
Review
</Button>
</div>
</>
Expand Down
2 changes: 1 addition & 1 deletion src/components/PositionManager/PositionActionBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const PositionActionBoundary: FC<
const { hasRewards, isDelegated, numActiveVotes } = position;
const hasVotes = numActiveVotes > 0;
const hasBlockers = hasRewards || isDelegated || hasVotes;
const canDoWhileBlocked = action === "delegate" || action == "proxy";
const canDoWhileBlocked = action === "delegate" || action === "proxy" || action === "transferOwnership";

if (!action) {
return children;
Expand Down
Loading
Loading