diff --git a/assets/images/webp/giddy-receive.webp b/assets/images/webp/giddy-receive.webp new file mode 100644 index 0000000..8085ecf Binary files /dev/null and b/assets/images/webp/giddy-receive.webp differ diff --git a/assets/images/webp/giddy-send.webp b/assets/images/webp/giddy-send.webp new file mode 100644 index 0000000..68f2893 Binary files /dev/null and b/assets/images/webp/giddy-send.webp differ diff --git a/assets/js/webapp/swapUtils.js b/assets/js/webapp/swapUtils.js index a15c0ba..3ff11d9 100644 --- a/assets/js/webapp/swapUtils.js +++ b/assets/js/webapp/swapUtils.js @@ -1,104 +1,92 @@ // assets/js/webapp/swapUtils.js +// Helper to handle cancellations silently +const handleCancel = (err) => { + const msg = err?.message || ""; + if (msg.includes("rejected") || msg.includes("cancelled") || msg.includes("user declined")) { + console.log("[Ultra] Swap cancelled"); + throw new Error("USER_REJECTED"); + } + return false; +}; + // ==================== ULTRA SWAP (Primary) ==================== async function performUltraSwap(inputMint, outputMint, rawAmount, provider, connectedWallet) { try { console.log(`[Ultra] Requesting quote: ${rawAmount} from ${inputMint} to ${outputMint}`); - const ultraRes = await fetch( `https://lite-api.jup.ag/ultra/v1/order?inputMint=${inputMint}&outputMint=${outputMint}&amount=${rawAmount}&taker=${connectedWallet}` ); - if (!ultraRes.ok) { - const errText = await ultraRes.text().catch(() => ''); - throw new Error(`Ultra HTTP ${ultraRes.status}: ${errText}`); - } - + if (!ultraRes.ok) throw new Error(`Ultra HTTP ${ultraRes.status}`); const quote = await ultraRes.json(); - if (quote.error) throw new Error(`Ultra Quote Error: ${JSON.stringify(quote.error)}`); - if (!quote.transaction) throw new Error("Ultra returned no transaction"); - - console.log(`[Ultra] Success | Router: ${quote.router || 'unknown'}`); - + return await executeUltraTransaction(quote, provider); } catch (error) { - // Suppress logging if the user simply cancelled the swap - if (error.message !== "USER_REJECTED") { - console.error("[Ultra] Failed:", error.message); - } + if (!handleCancel(error)) console.error("[Ultra] Failed:", error.message); throw error; } } -// ==================== SMART SIGNING (Injected + Browser SDK) ==================== +// ==================== SMART SIGNING ==================== async function executeUltraTransaction(quote, provider) { try { - const txBuffer = Buffer.from(quote.transaction, 'base64'); - const vtx = solanaWeb3.VersionedTransaction.deserialize(txBuffer); - const connectionMethod = window.connectionMethod || localStorage.getItem('connection_method'); - let signedTx; - // 1. PHANTOM BROWSER SDK (Google / Apple) + // ==================== GOOGLE / APPLE (Embedded Wallet) ==================== if (connectionMethod === 'google' || connectionMethod === 'apple') { - console.log("[Ultra] Signing with Phantom Browser SDK (solana namespace)..."); + console.log("[Ultra] Embedded wallet detected → Using v1 proxy + SDK signing"); + console.log(`[Ultra] Connected wallet: ${window.connectedWallet}`); + + const proxyRes = await fetch('https://giddy-key-swaps-production.up.railway.app/api/swap/v1', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + inputMint: quote.inputMint || "So11111111111111111111111111111111111111112", + outputMint: quote.outputMint, + rawAmount: quote.inAmount, + connectedWallet: window.connectedWallet + }) + }); + + const data = await proxyRes.json(); + if (!data.success) throw new Error(data.error || "v1 proxy failed"); + + const tx = solanaWeb3.VersionedTransaction.deserialize(Buffer.from(data.swapTransaction, "base64")); const sdk = await window.getPhantomSDK?.(); - if (!sdk?.solana) throw new Error("Phantom SDK solana provider not available"); - - try { - signedTx = await sdk.solana.signTransaction(vtx); - } catch (err) { - // Check for user rejection - if (err.message && (err.message.includes("rejected") || err.message.includes("cancelled"))) { - throw new Error("USER_REJECTED"); - } - throw err; - } - } - // 2. INJECTED PHANTOM (Extension / In-App) - else { - console.log("[Ultra] Signing with Injected Phantom Provider..."); - try { - signedTx = await provider.signTransaction(vtx); - } catch (err) { - if (err.message && (err.message.includes("rejected") || err.message.includes("cancelled"))) { - throw new Error("USER_REJECTED"); - } - throw err; - } + if (!sdk?.solana) throw new Error("Phantom SDK not available"); + + console.log("[Ultra] Requesting SDK signAndSendTransaction..."); + // Removed presignTransaction hook to prevent 403 Forbidden on /prepare + const result = await sdk.solana.signAndSendTransaction(tx); + + console.log("[Ultra] SDK Success, TXID:", result.signature); + return { success: true, txid: result.signature, router: "v1-proxy" }; + } + + // ==================== INJECTED PHANTOM ==================== + console.log("[Ultra] Signing with Injected Phantom..."); + if (!provider || typeof provider.signTransaction !== 'function') { + throw new Error("No valid injected provider"); } - // Serialize and Execute - const signedBytes = signedTx.serialize(); - const signedTxBase64 = btoa(String.fromCharCode(...new Uint8Array(signedBytes))); + const vtx = solanaWeb3.VersionedTransaction.deserialize(Buffer.from(quote.transaction, 'base64')); + const signed = await provider.signTransaction(vtx); + const signedTxBase64 = btoa(String.fromCharCode(...new Uint8Array(signed.serialize()))); const executeRes = await fetch('https://lite-api.jup.ag/ultra/v1/execute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - signedTransaction: signedTxBase64, - requestId: quote.requestId - }) + body: JSON.stringify({ signedTransaction: signedTxBase64, requestId: quote.requestId }) }); - if (!executeRes.ok) { - const errText = await executeRes.text().catch(() => ''); - throw new Error(`Ultra Execute Failed: ${executeRes.status} ${errText}`); - } - + if (!executeRes.ok) throw new Error(`Ultra Execute Failed: ${executeRes.status}`); const result = await executeRes.json(); - return { - success: true, - txid: result.signature, - router: quote.router || 'OKX/DFlow' - }; - + return { success: true, txid: result.signature, router: quote.router || 'OKX/DFlow' }; } catch (error) { - if (error.message !== "USER_REJECTED") { - console.error("[Ultra] Execute failed:", error); - } + if (!handleCancel(error)) console.error("[Ultra] Execute failed:", error); throw error; } } @@ -106,8 +94,7 @@ async function executeUltraTransaction(quote, provider) { // ==================== V1 FALLBACK ==================== async function performV1Swap(inputMint, outputMint, rawAmount, provider, connectedWallet) { try { - const proxyUrl = getApiUrl('/api/swap/v1'); - const proxyRes = await fetch(proxyUrl, { + const proxyRes = await fetch('https://giddy-key-swaps-production.up.railway.app/api/swap/v1', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ inputMint, outputMint, rawAmount, connectedWallet }) @@ -116,19 +103,11 @@ async function performV1Swap(inputMint, outputMint, rawAmount, provider, connect const data = await proxyRes.json(); if (!data.success) throw new Error(data.error || "v1 proxy failed"); - const tx = solanaWeb3.VersionedTransaction.deserialize( - Buffer.from(data.swapTransaction, "base64") - ); - + const tx = solanaWeb3.VersionedTransaction.deserialize(Buffer.from(data.swapTransaction, "base64")); const result = await provider.signAndSendTransaction(tx); - - return { - success: true, - txid: result.signature, - version: "v1" - }; + return { success: true, txid: result.signature, version: "v1" }; } catch (error) { - console.error("[V1 Proxy] Failed:", error.message); + if (!handleCancel(error)) console.error("[V1 Proxy] Failed:", error.message); throw error; } } @@ -137,4 +116,7 @@ async function performV1Swap(inputMint, outputMint, rawAmount, provider, connect window.performUltraSwap = performUltraSwap; window.performV1Swap = performV1Swap; -console.log("✅ swapUtils.js loaded (Robust SDK, Provider support + Silent Cancel)"); \ No newline at end of file +// Dispatch ready event +window.dispatchEvent(new CustomEvent('swap-engine-ready')); + +console.log("✅ swapUtils.js loaded and READY"); \ No newline at end of file diff --git a/wallet.html b/wallet.html index a5b8e80..8a77434 100644 --- a/wallet.html +++ b/wallet.html @@ -582,12 +582,256 @@
- -
-
-