From 55755bd91ba1d1d79b9c5d460366ad17b90065d3 Mon Sep 17 00:00:00 2001 From: Quazia Date: Thu, 22 May 2025 17:06:55 -0400 Subject: [PATCH] feat: solana send transaction Still needs cleanup but functional --- src/app/providers.tsx | 2 +- src/components/Demo.tsx | 80 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/app/providers.tsx b/src/app/providers.tsx index 23a56b5..29283d8 100644 --- a/src/app/providers.tsx +++ b/src/app/providers.tsx @@ -20,7 +20,7 @@ const FarcasterSolanaProvider = dynamic( ); export function Providers({ session, children }: { session: Session | null, children: React.ReactNode }) { - const solanaEndpoint = process.env.NEXT_PUBLIC_SOLANA_ENDPOINT || "https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY"; + const solanaEndpoint = process.env.SOLANA_RPC_ENDPOINT || "https://solana-rpc.publicnode.com"; return ( diff --git a/src/components/Demo.tsx b/src/components/Demo.tsx index 526c57e..4b30a54 100644 --- a/src/components/Demo.tsx +++ b/src/components/Demo.tsx @@ -433,6 +433,9 @@ export default function Demo( Address:
{truncateAddress(solanaAddress)}
+
+ +
)} @@ -484,6 +487,83 @@ function SignSolanaMessage({ signMessage }: { signMessage?: (message: Uint8Array ); } +function SendSolana() { + const [state, setState] = useState< + | { status: 'none' } + | { status: 'pending' } + | { status: 'error'; error: Error } + | { status: 'success'; signature: string } + >({ status: 'none' }); + + const { connection: solanaConnection } = useSolanaConnection(); + const { sendTransaction, publicKey } = useSolanaWallet(); + + const ashoatsPhantomSolanaWallet = 'Ao3gLNZAsbrmnusWVqQCPMrcqNi6jdYgu8T6NCoXXQu1'; + + const handleSend = useCallback(async () => { + setState({ status: 'pending' }); + try { + if (!publicKey) { + throw new Error('no Solana publicKey'); + } + + const { blockhash } = await solanaConnection.getLatestBlockhash(); + if (!blockhash) { + throw new Error('failed to fetch latest Solana blockhash'); + } + + // Set both fromPubkey and toPubkey to constants for debugging + const fromPubkeyStr = publicKey; + const toPubkeyStr = new (await import('@solana/web3.js')).PublicKey(ashoatsPhantomSolanaWallet); // TODO: Replace with a real base58 pubkey string + console.error('Debug Solana transfer:', { fromPubkeyStr, toPubkeyStr }); + const transaction = new (await import('@solana/web3.js')).Transaction(); + transaction.add( + (await import('@solana/web3.js')).SystemProgram.transfer({ + fromPubkey: publicKey, + toPubkey: toPubkeyStr, + lamports: 0n, + }), + ); + transaction.recentBlockhash = blockhash; + transaction.feePayer = new (await import('@solana/web3.js')).PublicKey(fromPubkeyStr); + + const simulation = await solanaConnection.simulateTransaction(transaction); + if (simulation.value.err) { + // Gather logs and error details for debugging + const logs = simulation.value.logs?.join('\n') ?? 'No logs'; + const errDetail = JSON.stringify(simulation.value.err); + throw new Error(`Simulation failed: ${errDetail}\nLogs:\n${logs}`); + } + const signature = await sendTransaction(transaction, solanaConnection); + setState({ status: 'success', signature }); + } catch (e) { + if (e instanceof Error) { + setState({ status: 'error', error: e }); + } else { + setState({ status: 'none' }); + } + } + }, [sendTransaction, publicKey, solanaConnection]); + + return ( + <> + + {state.status === 'error' && renderError(state.error)} + {state.status === 'success' && ( +
+
Hash: {truncateAddress(state.signature)}
+
+ )} + + ); +} + function SignMessage() { const { isConnected } = useAccount(); const { connectAsync } = useConnect();