Skip to content

Commit 0f0c4fd

Browse files
add pending work towards Helius integration
1 parent 9e002ab commit 0f0c4fd

File tree

6 files changed

+244
-126
lines changed

6 files changed

+244
-126
lines changed

components/QuickBuy/Sell.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const Sell = ({ lists, updateLists, onSeeOptions, onLoading }: SellProps) => {
3030
const [creatingAd, setCreatingAd] = useState(false);
3131
const [loading, setLoading] = useState(false);
3232
const { user } = useUserProfile({});
33+
const isWalletConnected = !!user?.contract_address;
3334

3435
// const [fee,setFee] = useState<bigint>();
3536

@@ -47,17 +48,19 @@ const Sell = ({ lists, updateLists, onSeeOptions, onLoading }: SellProps) => {
4748
// } , [token]);
4849

4950
//@ts-ignore
50-
// Use the useEscrowFee hook to get the fee data
51-
const {fee, loadingContract } = useContractRead(
52-
user?.contract_address ||'',
53-
"fee",
54-
false
51+
// Always call the hook, but pass null if wallet isn't connected
52+
const { fee, loadingContract } = useContractRead(
53+
isWalletConnected ? user.contract_address : null,
54+
'escrowState'
5555
);
56-
console.log(fee,loadingContract);
56+
57+
console.log("fee, loadingContract from Sell.tsx", fee, loadingContract);
58+
5759
// Fallback fee calculation
58-
const fallbackFee = tokenAmount
59-
? (BigInt(tokenAmount * 10 ** (token?.decimals || 0)) * BigInt(10 ** (token?.decimals || 0)) * BigInt(5)) /
60-
BigInt(10000)
60+
const fallbackFee = tokenAmount && token?.decimals
61+
? (BigInt(tokenAmount * 10 ** token.decimals) *
62+
BigInt(10 ** token.decimals) *
63+
BigInt(5)) / BigInt(10000)
6164
: null;
6265

6366
const updateLoading = (l: boolean) => {
@@ -135,6 +138,9 @@ console.log(fee,loadingContract);
135138
}
136139
};
137140

141+
// Add null check for fee calculation
142+
const finalFee = (fee || fallbackFee || BigInt(0)) / BigInt(LAMPORTS_PER_SOL);
143+
138144
return (
139145
<>
140146
<div className={`${creatingAd ? "hidden" : ""}`}>
@@ -207,12 +213,12 @@ console.log(fee,loadingContract);
207213

208214
<div className="text-center mt-4">
209215
{/* Display the fee if available, otherwise use the fallback fee */}
210-
{!!(fee || (fallbackFee)) && !!token && (
216+
{!!(fee || fallbackFee) && token?.decimals && (
211217
<span className="text-xs text-gray-600 text-center">
212-
Total fee: {(formatUnits((fee || fallbackFee) / BigInt(LAMPORTS_PER_SOL), token.decimals))}{" "}
218+
Total fee: {formatUnits((fee || fallbackFee || BigInt(0)) / BigInt(LAMPORTS_PER_SOL), token.decimals)}{" "}
213219
{token.symbol}
214-
</span>
215-
)}
220+
</span>
221+
)}
216222
</div>
217223
</div>
218224
<div className={`${!creatingAd ? "hidden" : ""}`}>

contexts/ConnectionContext.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Connection } from "@solana/web3.js";
2+
import React, { createContext, useContext, useEffect, useRef, useState } from "react";
3+
import { NEXT_PUBLIC_SOLANA_RPC } from 'utils';
4+
5+
interface ConnectionContextType {
6+
connection: Connection | null;
7+
getConnection: () => Connection;
8+
}
9+
10+
const ConnectionContext = createContext<ConnectionContextType | null>(null);
11+
12+
let cachedConnection: Connection | null = null;
13+
14+
export function ConnectionProvider({ children }: { children: React.ReactNode }) {
15+
const connectionRef = useRef<Connection | null>(null);
16+
17+
useEffect(() => {
18+
const initializeConnection = async () => {
19+
if (!cachedConnection) {
20+
const apiKey = process.env.NEXT_PUBLIC_HELIUS_API_KEY;
21+
const rpcUrl = `${NEXT_PUBLIC_SOLANA_RPC}?api-key=${apiKey}`;
22+
23+
cachedConnection = new Connection(rpcUrl, {
24+
commitment: 'confirmed',
25+
confirmTransactionInitialTimeout: 60000
26+
});
27+
}
28+
connectionRef.current = cachedConnection;
29+
};
30+
31+
initializeConnection();
32+
33+
return () => {
34+
connectionRef.current = null;
35+
};
36+
}, []);
37+
38+
const getConnection = () => {
39+
if (!connectionRef.current) {
40+
throw new Error("Connection not initialized");
41+
}
42+
return connectionRef.current;
43+
};
44+
45+
return (
46+
<ConnectionContext.Provider value={{ connection: connectionRef.current, getConnection }}>
47+
{children}
48+
</ConnectionContext.Provider>
49+
);
50+
}
51+
52+
export const useConnection = () => {
53+
const context = useContext(ConnectionContext);
54+
if (!context) {
55+
throw new Error("useConnection must be used within a ConnectionProvider");
56+
}
57+
return context;
58+
};
Lines changed: 90 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,121 @@
1-
// hooks/transactions/useContractRead.ts
2-
31
import { useState, useEffect } from "react";
42
import { PublicKey } from "@solana/web3.js";
53
import useLocalSolana from "./useLocalSolana";
4+
import { BN } from "@coral-xyz/anchor";
5+
6+
interface ContractReadResult {
7+
data: any;
8+
fee: bigint | null;
9+
loadingContract: boolean;
10+
}
611

712
export const useContractRead = (
8-
contractAddress: string,
13+
contractAddress: string | null,
914
method: string
10-
) => {
15+
): ContractReadResult => {
16+
const [fee, setFee] = useState<bigint | null>(null);
1117
const [data, setData] = useState<any>(null);
12-
const [loading, setLoading] = useState(true);
13-
const [error, setError] = useState<string | null>(null);
14-
const { program, connection, getConnection } = useLocalSolana();
18+
const [loadingContract, setLoading] = useState(true);
19+
const { program, getConnection, getEscrowStatePDA, isConnectionReady } = useLocalSolana();
1520

1621
useEffect(() => {
1722
const fetchData = async () => {
23+
24+
// If contractAddress is null, skip fetching
25+
if (!contractAddress) {
26+
setLoading(false);
27+
return;
28+
}
29+
30+
// Check if connection is ready
31+
if (!isConnectionReady) {
32+
console.warn("Connection is not ready");
33+
setLoading(false);
34+
return;
35+
}
36+
37+
// Check if connection and program are available
38+
if (!program) {
39+
console.warn("Program not established");
40+
setLoading(false);
41+
return;
42+
}
43+
44+
// Check if contract address is provided
45+
if (!contractAddress) {
46+
console.warn("Contract address is required");
47+
setLoading(false);
48+
return;
49+
}
50+
1851
try {
1952
setLoading(true);
2053

21-
if (!connection) {
22-
throw new Error("Connection not established");
54+
let publicKey: PublicKey;
55+
if (method === "escrowState") {
56+
// Get the PDA for the escrow state
57+
const escrowStateAddress = getEscrowStatePDA(contractAddress);
58+
if (!escrowStateAddress) {
59+
console.warn("Unable to find LocalSolana account");
60+
setLoading(false);
61+
return;
62+
}
63+
publicKey = escrowStateAddress;
64+
} else {
65+
publicKey = new PublicKey(contractAddress);
2366
}
2467

25-
if (!contractAddress) {
26-
throw new Error("Contract address is required");
27-
}
68+
console.log("Fetching account info for publicKey:", publicKey.toBase58());
2869

29-
const publicKey = new PublicKey(contractAddress);
70+
// Fetch account information
3071
const accountInfo = await getConnection().getAccountInfo(publicKey);
31-
3272
if (!accountInfo?.data) {
33-
throw new Error("Unable to retrieve account information");
73+
console.warn("Unable to retrieve account information");
74+
setLoading(false);
75+
return;
3476
}
3577

36-
// Decode data using the Anchor program
37-
const decodedData = program?.account[method]?.coder?.accounts.decode(
38-
method,
39-
accountInfo.data
40-
);
78+
// Decode data based on the method
79+
let decodedData;
80+
switch (method) {
81+
case "escrow":
82+
decodedData = program.account.escrow.coder.accounts.decode(
83+
"escrow",
84+
accountInfo.data
85+
);
86+
if (decodedData?.fee) {
87+
setFee(BigInt(decodedData.fee.toString()));
88+
}
89+
break;
4190

42-
setData(decodedData || null);
91+
case "escrowState":
92+
decodedData = program.account.escrowState.coder.accounts.decode(
93+
"escrowState",
94+
accountInfo.data
95+
);
96+
97+
if (decodedData?.fee) {
98+
setFee(BigInt(decodedData.fee.toString()));
99+
}
100+
101+
setData(decodedData);
102+
103+
default:
104+
console.warn(`Unsupported method: ${method}`);
105+
setLoading(false);
106+
return;
107+
}
43108
} catch (err: any) {
44109
console.error("Error fetching contract data:", err.message);
45-
setError(err.message);
110+
setFee(null);
46111
setData(null);
47112
} finally {
48113
setLoading(false);
49114
}
50115
};
51116

52117
fetchData();
53-
}, [contractAddress, method, connection]);
118+
}, [contractAddress, method, program, isConnectionReady]);
54119

55-
return { data, loading, error };
56-
};
120+
return { fee, data, loadingContract };
121+
};

0 commit comments

Comments
 (0)